Pulumi Error: 'command failed' From the Automation API
Fix Pulumi Automation API 'CommandError: code: 255, stderr' failures wrapping pulumi up/preview: surface the real error, stream logs, and handle concurrent-update conflicts.
- #pulumi
- #iac
- #troubleshooting
- #errors
Stuck on this Pulumi error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Exact Error Message
CommandError:
code: 255
stdout:
stderr: error: update failed
err?: undefined
at /app/node_modules/@pulumi/pulumi/automation/errors.js:57:23
at ChildProcess.<anonymous> (.../automation/cmd.js:120:31)
In Python and Go you see the same wrapped failure with a different type name:
pulumi.automation.errors.CommandError: code: 255
stderr: error: 1 error occurred:
* updating urn:pulumi:dev::app::aws:s3/bucket:Bucket::data: creating S3 Bucket: BucketAlreadyExists
What It Means
The Automation API runs the ordinary pulumi CLI as a child process and inspects its exit code. When pulumi up, pulumi preview, pulumi destroy, or pulumi refresh exits non-zero, the SDK throws a CommandError (CommandError in Node/Python, autoError in Go) that wraps the underlying CLI failure. The wrapper is generic; the real cause is almost always in the stderr field, which contains the exact same message you would see running the command by hand.
code: 255 is Pulumi’s normal “the operation failed” exit code. It does not indicate an Automation-API bug. Your job is to unwrap the message and treat it exactly as the equivalent CLI error.
Common Causes
- A genuine resource error during the wrapped operation (permissions, duplicate names, provider errors) that the wrapper hides behind a generic message.
- Output was not streamed, so the real error text is only in the exception’s
stderrand easy to miss. - Two Automation-API processes ran against the same stack, producing a concurrent-update / stack-locked failure.
- Missing plugins or provider config because the automation program did not run
installPlugins/refreshor set required config beforeup. - A compile/type error in an inline or local program, which fails before any resource is touched.
- Credentials available in your shell but not in the process environment the Automation API spawned.
Diagnostic Commands
The single most important step is to print the wrapped stderr. In Node:
try {
await stack.up({ onOutput: process.stdout.write.bind(process.stdout) });
} catch (err) {
console.error("real cause:", (err as any).stderr);
throw err;
}
Reproduce the same operation with the plain CLI to confirm the underlying error outside the wrapper:
pulumi up --stack dev --cwd ./infra
Check whether the stack is locked by another run:
pulumi cancel --stack dev
Confirm plugins and config the automation program expects are actually present:
pulumi plugin ls
pulumi config --stack dev
Step-by-Step Resolution
- Always attach an
onOutput(oron_output) handler so the CLI’s real messages stream live instead of hiding in the exception:
const result = await stack.up({ onOutput: (msg) => process.stdout.write(msg) });
-
Inspect
err.stderr(or the exception message in Python/Go) and fix the underlying resource error it reports — treat it exactly as the same standalone CLI error. -
Make the automation program deterministic by installing plugins and refreshing before updating:
await stack.workspace.installPlugin("aws", "v6.0.0");
await stack.refresh({ onOutput: process.stdout.write.bind(process.stdout) });
- If the failure is a concurrent-update lock, ensure only one process touches a stack at a time, and clear a stale lock deliberately:
pulumi cancel --stack dev --yes
- Ensure the child process inherits credentials by passing them through
envVarson the stack settings, then re-run and confirm success:
await stack.setAllConfig({ "aws:region": { value: "us-east-1" } });
await stack.up({ onOutput: process.stdout.write.bind(process.stdout) });
Prevention
- Never swallow the exception: log
stderr(Node),str(err)(Python), or the wrapped error (Go) on every failure so the real cause is visible. - Stream output with
onOutput/on_outputin every Automation-API call, including CI runs. - Serialize updates per stack; use a queue or lock so two automation processes never update the same stack at once.
- Call
installPlugins/installPluginand set required config in the program so runs are reproducible across machines. - Pass credentials explicitly through the workspace
envVarsrather than assuming the parent shell’s environment is inherited.
Related Errors
the stack is currently locked— a concurrent update the wrapper surfaces as aCommandError.no resource plugin found— a missing provider plugin that failed the wrappedup.error: could not load plugin for provider— provider install/config gap inside the automation run.TypeScript error/ compile failure — an inline-program error thrown before resources are created.
Frequently Asked Questions
Where is the actual error hidden in a CommandError? In the stderr field of the exception. The top-level message is a generic wrapper; log err.stderr (or str(err) in Python) to see the identical text the CLI would print.
Why does code 255 keep appearing? 255 is Pulumi’s standard non-zero exit for a failed operation, not a specific fault. Read the stderr to learn what actually failed.
How do I see progress instead of one big failure at the end? Pass an onOutput callback (Node/Go) or on_output (Python) to up/preview/destroy so the CLI streams live, matching interactive output.
How do I handle a stack that is locked by a previous automation run? Serialize your runs, and clear a genuinely stale lock with pulumi cancel --stack <name>. Ready-made automation snippets live in the Pulumi prompt library.
Is a CommandError a bug in the Automation API? Almost never. It faithfully reports that the wrapped CLI command failed. Fix the underlying resource error and the wrapper clears. More fixes are in the Pulumi guides.
Fixed it? Get 500 Pulumi & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.