Skip to main content

My declaragent deploy got 403

The single most common Cloud Run failure. gcloud run services replace returns HTTP 403 + a cryptic Permission 'run.services.create' denied.

Flowchart

The three IAM roles that matter

RoleWhy it's needed
roles/run.adminCreate + update the Cloud Run service.
roles/iam.serviceAccountUserAttach a service account to a Cloud Run revision.
roles/secretmanager.secretAccessorBind ${secret:...} refs into env vars.

There is no built-in IAM preflight today — check the roles yourself before deploying:

PRINCIPAL="user:you@example.com"
PROJECT="my-project"

gcloud projects get-iam-policy "$PROJECT" \
--flatten="bindings[].members" \
--filter="bindings.members:$PRINCIPAL" \
--format="value(bindings.role)"

If any of the three roles is missing from the output, grant it (next section) before running gcloud.

Quick fixes

# The deploying principal — usually your gcloud user.
PRINCIPAL="user:you@example.com"
PROJECT="my-project"

gcloud projects add-iam-policy-binding "$PROJECT" \
--member="$PRINCIPAL" --role="roles/run.admin"
gcloud projects add-iam-policy-binding "$PROJECT" \
--member="$PRINCIPAL" --role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding "$PROJECT" \
--member="$PRINCIPAL" --role="roles/secretmanager.secretAccessor"

After the deploy

declaragent deploy gcp-cloud-run --verify is a post-deploy health check: it runs gcloud run services describe on the deployed service and probes its /health endpoint. Use it to confirm a deploy that succeeded is actually serving — it cannot diagnose a 403 that prevented the service from being created in the first place.

Still stuck

  • Run declaragent deploy gcp-cloud-run --verify and paste the full output into a GitHub issue, together with the get-iam-policy output above.
  • Confirm the Dockerfile + service.yaml generators emitted the expected secret bindings by inspecting .declaragent/deploy/service.yaml.