hashicorp/terraform · error
failed to clean up file lock after DynamoDB lock error: %v;
Error message
failed to clean up file lock after DynamoDB lock error: %v; original error: %w
What it means
Thrown in RemoteClient.Lock() (s3/client.go:336) in the double-locking mode (useLockFile=true AND a dynamodb_table is configured). lockWithFile succeeded (S3 .tflock created) but lockWithDynamoDB failed, and the compensating unlockWithFile ALSO failed. The error bundles both: the cleanup failure (%v) and the original DynamoDB lock error (%w). A lock may be left in an inconsistent state.
Source
Thrown at internal/backend/remote-state/s3/client.go:336
log.Info("Attempting to lock remote state (DynamoDB only)...")
if err := c.lockWithDynamoDB(ctx, info); err != nil {
return "", err
}
log.Info("Locked remote state (DynamoDB only)")
return info.ID, nil
}
// double locking: dynamodb + file (design decision: both must succeed)
log.Info("Attempting to lock remote state (S3 Native and DynamoDB)...")
if err := c.lockWithFile(ctx, info, log); err != nil {
return "", err
}
if err := c.lockWithDynamoDB(ctx, info); err != nil {
// Release the file lock if attempting to acquire the DynamoDB lock fails.
if unlockErr := c.unlockWithFile(ctx, info.ID, &statemgr.LockError{}, log); unlockErr != nil {
return "", fmt.Errorf("failed to clean up file lock after DynamoDB lock error: %v; original error: %w", unlockErr, err)
}
return "", err
}
log.Info("Locked remote state (S3 Native and DynamoDB)")
return info.ID, nil
}
// lockWithFile attempts to acquire a lock on the remote state by uploading a lock file to Amazon S3.
//
// This method is used when the S3 native locking mechanism is in use. It uploads a lock file (JSON)
// to an S3 bucket to establish a lock on the state file. If the lock file does not already
// exist, the operation will succeed, acquiring the lock. If the lock file already exists, the operation
// will fail due to a conditional write, indicating that the lock is already held by another Terraform client.
func (c *RemoteClient) lockWithFile(ctx context.Context, info *statemgr.LockInfo, log hclog.Logger) error {
lockFileJson, err := json.Marshal(info)
if err != nil {View on GitHub (pinned to c9def3e214)
Solutions
- Manually delete the stale <key>.tflock object in S3 and the DynamoDB LockID row if one was created.
- Fix the dynamodb_table name/permissions and the S3 delete permission, then retry.
- Run `terraform force-unlock` if Terraform still reports the state as locked.
- Consider using a single locking mechanism (file-only or DynamoDB-only) to avoid the double-lock cleanup path.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check both lock destinations are writable before locking
// _, ferr := s3Client.HeadObject(ctx, &s3.HeadObjectInput{Bucket:&bucket, Key:aws.String(lockFilePath)})
// _, derr := dynClient.DescribeTable(ctx, &dynamodb.DescribeTableInput{TableName:aws.String(ddbTable)}) Type guard
// The wrapped %w is the original DynamoDB lock error (often a *statemgr.LockError)
// var lockErr *statemgr.LockError
// if errors.As(err, &lockErr) { /* inspect lockErr.Info / Err */ } Try / catch
// On double-lock cleanup failure, force manual cleanup rather than retrying blindly
// _, err := client.Lock(info)
// if err != nil && strings.Contains(err.Error(), "failed to clean up file lock") {
// // delete stale .tflock + DynamoDB row, then force-unlock
// } Prevention
- Prefer a single locking mechanism (file-only or DynamoDB-only) to avoid the cleanup path.
- Ensure the role has both s3:PutObject/DeleteObject and dynamodb:PutItem/DeleteItem.
- Verify the dynamodb_table name exists before enabling double locking.
When it happens
Trigger: S3 lock file created, then DynamoDB PutItem failed (table missing/misspelled, ConditionalCheckFailedException, dynamodb:PutItem denied), and the subsequent S3 delete of the .tflock also failed (s3:DeleteObject denied, network error).
Common situations: Misconfigured dynamodb_table name combined with insufficient S3 delete permissions; partial AWS outage; IAM policy allows PutObject but not DeleteObject on the lock key.
Related errors
- failed to lock s3 state: %s
- Error unlocking S3 state. Lock ID: %s Error: %s You may ha
- failed to unlock both S3 and DynamoDB: S3 error: %v, DynamoD
- invalid md5
- Error unlocking Consul state. Lock ID: %s Error: %s You ma
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/9ea3c904700c8109.
Report an issue: GitHub.