Terraform S3 Native Lockfile Errors - use_lockfile in CI
With the S3 backend’s native locking (use_lockfile), the lock is an object in the bucket. A killed run can leave a stale .tflock behind, or missing S3 permissions can block creating/removing it.
What this error means
plan/apply fails acquiring the state lock when using S3 native locking, either because a stale .tflock object remains from a cancelled run or because the role cannot write/delete it. A stale lock clears once the killed run is gone or after force-unlock.
Error: Error acquiring the state lock
Error message: operation error S3: PutObject, the lock file
"app/terraform.tfstate.tflock" already existsCommon causes
Stale .tflock object from a killed run
A cancelled apply using use_lockfile may not delete its .tflock object, so the next run sees the lock as still held.
Missing S3 permissions for the lock object
Native locking needs s3:PutObject and s3:DeleteObject on the lock object path. Without delete, the lock cannot be released.
How to fix it
Force-unlock or remove the stale lock object
After confirming no apply is running, force-unlock; if needed, delete the lock object directly.
terraform force-unlock <LOCK_ID>
# or, only if confirmed stale:
aws s3 rm s3://my-tf-state/app/terraform.tfstate.tflockGrant delete permission on the lock object
Ensure the CI role can create and delete the lock object so locks release cleanly.
{
"Effect": "Allow",
"Action": ["s3:PutObject","s3:DeleteObject"],
"Resource": "arn:aws:s3:::my-tf-state/app/terraform.tfstate.tflock"
}How to prevent it
- Grant
s3:DeleteObjecton the lock path when usinguse_lockfile. - Serialize Terraform jobs so the lock is rarely contended.
- Avoid cancelling applies mid-run to prevent stale lock objects.