hashicorp/terraform · warning
Error unlocking S3 state. Lock ID: %s Error: %s You may ha
Error message
Error unlocking S3 state. Lock ID: %s Error: %s You may have to force-unlock this state in order to use it again.
What it means
Thrown by the lockUnlock cleanup helper in s3/backend_state.go:223 when stateMgr.Unlock() fails during the new-workspace init path. The message intentionally includes the Lock ID and tells the user a force-unlock may be required. It fires on the cleanup branch after the main operation errored or finished.
Source
Thrown at internal/backend/remote-state/s3/backend_state.go:223
exists = true
break
}
}
// We need to create the object so it's listed by States.
if !exists {
// take a lock on this state while we write it
lockInfo := statemgr.NewLockInfo()
lockInfo.Operation = "init"
lockId, err := client.Lock(lockInfo)
if err != nil {
return nil, diags.Append(fmt.Errorf("failed to lock s3 state: %s", err))
}
// Local helper function so we can call it multiple places
lockUnlock := func(parent error) error {
if err := stateMgr.Unlock(lockId); err != nil {
return fmt.Errorf(strings.TrimSpace(errStateUnlock), lockId, err)
}
return parent
}
// Grab the value
// This is to ensure that no one beat us to writing a state between
// the `exists` check and taking the lock.
if err := stateMgr.RefreshState(); err != nil {
err = lockUnlock(err)
return nil, diags.Append(err)
}
// If we have no state, we have to create an empty state
if v := stateMgr.State(); v == nil {
if err := stateMgr.WriteState(states.NewState()); err != nil {
err = lockUnlock(err)
return nil, diags.Append(err)
}View on GitHub (pinned to c9def3e214)
Solutions
- Run `terraform force-unlock <Lock ID>` with the ID from the message.
- Manually delete the stale <key>.tflock S3 object and the DynamoDB LockID row.
- Verify the role has s3:DeleteObject and dynamodb:DeleteItem permissions.
- Retry init once the lock is cleared.
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify delete permission on the lock key before init
// _, err := s3Client.DeleteObject(ctx, &s3.DeleteObjectInput{Bucket:&bucket, Key:aws.String("probe")}) // sandboxed Try / catch
// Unlock cleanup failure: warn and instruct force-unlock
// if err := stateMgr.Unlock(lockID); err != nil {
// log.Warn("state may still be locked; run terraform force-unlock", "id", lockID, "err", err)
// } Prevention
- Grant s3:DeleteObject on the .tflock key and dynamodb:DeleteItem on the lock row.
- Don't manually delete lock files out-of-band.
- After a crashed run, verify the lock is fully released before the next.
When it happens
Trigger: The lock was already released out-of-band; S3 DeleteObject of the .tflock failed (permissions/network); DynamoDB DeleteItem failed; the lock ID no longer matches the stored lock; connection/credentials dropped mid-cleanup.
Common situations: Interrupted init where the lock object was partially cleaned; another operator force-unlocked concurrently; IAM role lacks s3:DeleteObject on the lock key or dynamodb:DeleteItem.
Related errors
- failed to clean up file lock after DynamoDB lock error: %v;
- Error unlocking Azure state. Lock ID: %s Error: %s You may
- Error unlocking Consul state. Lock ID: %s Error: %s You ma
- %v Additionally, unlocking the state in Kubernetes faile
- lock id %q does not match existing lock
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/c70d6e36937db009.
Report an issue: GitHub.