IaC error catalogue — the API that is not enabled, the reconciler's identity, state locking, and a retired product
Cause, check and fix for the failures that stop an apply rather than a call: a service not enabled on the project, a permission error that names an identity you are not, an apply against a product that is out of support, and the state-bucket failures that have no undo.
markdownreferencev1YWX9-4X92stage: deploytrust: officialfamily: iacservice: terraforminterface: iacapi not enabledgcloud services enablegcloud services listservice usageterraform statestate lockconfig connector permissiondeployment manager end of support
IaC error catalogue
1. The service is not enabled on the project
The commonest first-apply failure on a fresh Google Cloud project, and it is not a permission problem.
| cause | the API the resource belongs to has never been enabled on this project |
| check | gcloud services list — does the API appear as enabled? |
| fix | gcloud services enable SERVICE, or several at once: gcloud services enable bigquery.googleapis.com pubsub.googleapis.com |
| role | Service Usage Admin, roles/serviceusage.serviceUsageAdmin |
| long-running | gcloud services operations describe operations/OPERATION_ID |
Recorded as an absence: the enable/disable page does not print the verbatim error a caller gets from a disabled API, so no string is quoted here. It does note the recursive case: disable the Service Usage API itself on the project making requests and "you receive an error when you attempt the request" — which is the one failure you cannot fix with the command above from that project.
For an estimate: enabling services is a per-project, per-API step. A landing zone with 12 projects and 20 APIs is 240 enablements, and they are a prerequisite of every other apply. Put them in the IaC, not in a runbook.
2. The permission error names an identity you are not
| cause | Config Connector reconciles as its own service account — verbatim, "not the identity of the human user or service account that submitted the manifest" |
| check | read the principal out of the error, then run Policy Troubleshooter for that principal (guides/identity/fix-permission-denied.md step 2) |
| fix | grant the role to the Config Connector identity; and remember Kubernetes RBAC and Google Cloud IAM are two separate gates |
The same shape bites in Infra Manager and in any CI runner: the identity that applies is not the identity that authored. Diagnosing with your own principal answers a question nobody asked.
3. An apply against a product that is out of support
| cause | the configuration is Cloud Deployment Manager, which "reached end of support on March 31, 2026" |
| check | is the template a Deployment Manager *.yaml with resources: and type: of the gcp-types/... form? |
| fix | do not extend it. reference/iac/deployment-manager-status.md §3 sets out what to establish before replacing it |
4. State failures, which are the ones with no undo
| Signature | Cause | Check | Fix |
|---|---|---|---|
a lock error on terraform apply | another apply holds the state lock, or a previous one died holding it | who else is applying? Check the CI concurrency, not the bucket | wait; break the lock only when you have established no apply is running. A broken lock during a live apply corrupts state |
| state is missing or truncated after a failed write | no object versioning on the state bucket | gcloud storage buckets describe — is versioning on? | restore the previous object version. If versioning was never enabled there is nothing to restore. Enable it before the first apply, which is why the vendor's own tutorial does |
| a plan that differs between two runs of the same configuration | the provider version is not pinned | is there a required_providers version constraint? | pin it. The Terraform-on-Google-Cloud page makes no version recommendation, so this is the hub's rule, not the vendor's |
terraform init loses local state | the backend was added without migrating | — | terraform init -migrate-state, which is the documented path |
5. The rule behind all four sections
An IaC failure is almost never the resource. It is the project's enabled services, the applying identity, the state, or a product that no longer exists. Check those four before reading the resource schema.
Next: guides/iac/terraform-first-apply.md runs them in order; guides/parity/iac.md compares this to
CloudFormation and ARM/Bicep.