Common Terraform and OpenTofu Errors and How to Fix Them

· 4 min read · Terraform & OpenTofu Tutorials

A troubleshooting guide #

When something fails, read the error from the top, find the resource it names and, if needed, increase the log level as shown in how to debug Terraform. These are the errors most often searched for, with the usual cause and fix.

Error acquiring the state lock #

Error: Error acquiring the state lock
Lock Info:
  ID:        3f1b0d6c-...
  Operation: OperationTypeApply
  Who:       user@host

Another run holds the lock or a previous run crashed. First check that nobody is running Terraform (including the CI pipeline). Then release it:

$ terraform force-unlock 3f1b0d6c-...

With the S3 native lock the lock is the object terraform.tfstate.tflock. Never force-unlock while a run is active: you can corrupt the state.

Error: No valid credential sources found / ExpiredToken #

Error: No valid credential sources found for AWS Provider.

Terraform cannot find AWS credentials. Check aws sts get-caller-identity with the same shell, AWS_PROFILE, AWS_REGION, expired SSO sessions (aws sso login) and, in CI, the OIDC role. See the AWS provider.

AccessDenied / UnauthorizedOperation #

Error: creating S3 Bucket: AccessDenied: Access Denied

The identity lacks the permission, or an SCP or permission boundary blocks it. The message names the action. Add it to the IAM policy or check SCPs. CloudTrail shows the denied call.

Already exists (EntityAlreadyExists, BucketAlreadyExists, InvalidKeyPair.Duplicate) #

The object exists in AWS but not in the state, perhaps from a failed run or manual creation. Import it or delete it. For S3, bucket names are global: pick another name.

Error: Provider produced inconsistent result after apply #

A provider bug or an eventual-consistency issue. Run plan and apply again. If it persists, upgrade the provider (terraform init -upgrade) and search the provider issues.

Error: Cycle #

Error: Cycle: aws_security_group.a, aws_security_group.b

Two resources reference each other. Split the rules into separate resources: see dependencies.

The "count" / "for_each" value depends on resource attributes that cannot be determined until apply #

Error: Invalid for_each argument
The "for_each" set includes values derived from resource attributes that cannot be determined until apply

The keys come from something that does not exist yet. Use keys that you define in variables or locals, or split the run in two with -target only as a temporary workaround. See for_each vs count.

Error: Unsupported argument / Unsupported block type #

Usually a provider version problem: the argument exists in another major version. Check the documentation for your version, and pin the version in required_providers. After upgrading AWS provider from 3.x to 4.x or 5.x many aws_s3_bucket arguments moved to separate resources (S3).

Error: Inconsistent dependency lock file #

Error: Inconsistent dependency lock file

The .terraform.lock.hcl does not match the providers required. Run terraform init -upgrade, and commit the updated lock file. To make a lock file work on several platforms: terraform providers lock -platform=linux_amd64 -platform=darwin_arm64.

Backend configuration changed #

Error: Backend configuration changed

Run terraform init -reconfigure to use the new configuration, or terraform init -migrate-state to move the state to the new backend.

Error: Invalid function argument / Invalid index #

Often an empty list: aws_instance.web[0] when count = 0. Use one(aws_instance.web[*].id) or try(). Check variable types and null values. See conditionals.

DependencyViolation when destroying #

Error: deleting EC2 Subnet: DependencyViolation: The subnet has dependencies and cannot be deleted

Something created outside Terraform still uses it (a network interface from a load balancer, Lambda or endpoint). Find it in the console (Network interfaces), delete it, and run destroy again.

Timeouts: context deadline exceeded #

Some resources take a long time (CloudFront, RDS, NAT gateways). Increase the timeouts block of the resource, and check quotas and network access.

Resource limits: LimitExceeded, VcpuLimitExceeded #

You reached an account quota. Request an increase in Service Quotas. Elastic IPs and VPCs per region are the usual ones.

Failed apply halfway #

The state records what was created. Fix the cause and run apply again: it continues from where it stopped. Resources marked tainted are recreated. See replace, taint and target.

Plan wants to recreate something unexpectedly #

Read the # forces replacement marker in the plan: it names the argument that cannot be changed in place. If the change is accidental (a tag, a name suffix), revert it in code. Protect critical resources with prevent_destroy.

Prevent errors #

Run fmt, validate, linters and scanners and tests in CI, and pin versions (best practices).

#Terraform #OpenTofu #AWS #Debug