Diagnosing and Fixing Pulumi State Lock Failures During Stack Updates
When Pulumi stack updates fail with lock errors, this guide walks you through a diagnostic table, ordered checks, fixes, and escalation steps to resolve state‑locking issues efficiently.
21 Jul 2025, 05:30 UTC

Recognizable Condition
When a pulumi up, pulumi refresh, or any stack‑modifying command stalls or fails with messages such as Failed to acquire state lock or Another operation is in progress, the Pulumi CLI is unable to obtain the exclusive lock that protects the stack’s state file. This lock is required to prevent concurrent modifications that could corrupt the state.
Cause & Diagnostic Table
| Possible Cause | Typical Symptoms | Diagnostic Check |
|---|---|---|
| Concurrent updates from multiple CLI or automation jobs | Command hangs for minutes; error shows lock acquisition failure | Check running processes and CI/CD job logs for the same stack name |
| Stale lock entry left by a crashed or interrupted run | Lock error persists even after all jobs appear stopped | Inspect the lock backend (e.g., DynamoDB table) for an existing lock item |
| Missing or unhealthy lock backend (e.g., DynamoDB table not created) | Error mentions missing backend resource or access denied | Verify backend resource exists and is in an ACTIVE state |
| Insufficient IAM permissions for lock operations | Permission denied errors when Pulumi tries to GetItem/PutItem/DeleteItem | Review the IAM policy attached to the role or user used by Pulumi |
| Interrupted run that left the state file partially updated | Subsequent updates fail or state shows inconsistencies | Check recent update logs for abrupt exits or network failures |
Ordered Checks
- Confirm No Parallel Jobs
Runps -ef | grep pulumion the machine, and review CI/CD pipelines for any jobs that might still be running against the same stack. If any are found, wait for them to finish or cancel them. - Validate Lock Backend Health
For an S3 backend with DynamoDB locking, use:
Verify the table status isaws dynamodb describe-table --table-name pulumi-lock-ACTIVEand that the endpoint is reachable. - Check IAM Permissions
Ensure the user/role executing Pulumi has at least:dynamodb:GetItemdynamodb:PutItem
If using a custom policy, add these actions for the lock table ARN.dynamodb:DeleteItem - Inspect Recent Logs for Abrupt Termination
Runpulumi stack history --stackand look for entries with statusFAILEDorABORTED. Correlate timestamps with your system’s process logs. - Attempt Manual Lock Release (if safe)
If you have confirmed no other updates are running, you can manually release the lock:
This command removes the lock entry from the backend. Use only when you are certain the stack is idle.pulumi cancel --yes
Fixes Tied to Findings
- Concurrent Updates – Serialize CI/CD triggers or add a pre‑step that checks for an existing lock using
pulumi stack --show-outputsbefore starting the deployment. - Stale Lock Entry – After confirming no active run, delete the lock item directly:
aws dynamodb delete-item \ --table-name pulumi-lock- \ --key '{"StackName":{"S":""}}' - Missing Lock Backend – Create the DynamoDB table with the schema Pulumi expects:
aws dynamodb create-table \ --table-name pulumi-lock- \ --attribute-definitions AttributeName=StackName,AttributeType=S \ --key-schema AttributeName=StackName,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 - Insufficient IAM Permissions – Attach the following policy snippet to the role/user:
{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["dynamodb:GetItem","dynamodb:PutItem","dynamodb:DeleteItem"],"Resource":"arn:aws:dynamodb:*:*:table/pulumi-lock-"}]} - Interrupted Run – Re‑run the update after a clean lock release, and consider adding a
pulumi refreshstep to reconcile state.
Escalation Criteria
- Lock persists after manual release attempts.
- Backend health checks (e.g., DynamoDB describe‑table) repeatedly fail.
- Multiple stacks in the same environment exhibit lock failures, suggesting a systemic configuration or permission issue.
- You lack the necessary permissions to modify the lock backend or IAM policies.
Verification Steps
- Run
pulumi stack select <stack-name>followed bypulumi up --refresh. Observe that the lock is acquired within a few seconds and released without error. - Check the backend (e.g., DynamoDB) to confirm
GetItem,PutItem, andDeleteItemoperations succeeded during the run by enabling CloudWatch metrics for the table. - Verify
pulumi stack historyshows a successful update and that no subsequent runs produce lock errors.
Limitations and Precautions
- Deleting a lock entry while an update is in progress can corrupt the state. Always ensure the stack is idle before manual intervention.
- Modifying lock backend configuration should be tested in a non‑production stack first to avoid unintended state migration issues.
- Pulumi’s lock mechanism is backend‑specific; the commands above assume an S3 backend with DynamoDB locking. For other backends (e.g., Azure Blob Storage), adjust the lock resource accordingly.
Practical Example: S3 Backend with DynamoDB Lock
Assume a stack named dev-app configured with the following Pulumi configuration:
pulumi config set aws:region us-west-2
pulumi config set pulumi:backend s3://my-pulumi-state/dev-app
# DynamoDB lock table is created automatically by Pulumi if not present
During a pipeline run, the command fails with Failed to acquire state lock. Following the diagnostic guide:
- Check for other runs:
ps -ef | grep pulumishows none. - Describe the lock table:
aws dynamodb describe-table --table-name pulumi-lock-dev-appreturns statusACTIVE. - IAM policy review confirms
dynamodb:GetItemmissing; add it. - Re‑run
pulumi up– lock is acquired successfully.
After the fix, pulumi stack history shows a successful update, and subsequent runs complete without lock errors.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.