Pulumi Error: 'Running program failed with an unhandled exception' — Cause, Fix, and Troubleshooting Guide
Fix Pulumi 'Running program failed with an unhandled exception' when your Node.js/TypeScript Pulumi program throws an uncaught error. Causes and fixes.
- #pulumi
- #iac
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
error: Running program '/app' failed with an unhandled exception: means your Pulumi program itself threw an exception that nothing caught. The Node.js language host (pulumi-language-nodejs) runs your index.ts/index.js, and when that code throws — synchronously, in a promise, or inside an .apply() callback — the host reports it back to the engine as an unhandled exception and aborts the deployment.
This is a generic wrapper: the real cause is always printed on the lines below it, typically a JavaScript stack trace. The path shown ('/app', or your project directory) is just the program’s working directory. Your job is to read the underlying exception and fix the offending code or configuration.
error: Running program '/app' failed with an unhandled exception:
TypeError: Cannot read properties of undefined (reading 'id')
at /app/index.ts:42:31
at processTicksAndRejections (node:internal/process/task_queues:95:5)
Symptoms
pulumi uporpulumi previewfails during the program-execution phase, before or during resource registration.- The banner line is followed by a Node.js/TypeScript stack trace pointing into your own source files.
- Errors like
TypeError,ReferenceError,SyntaxError, thrownError("..."), or an unhandled promise rejection appear underneath. pulumi previewfails the same waypulumi updoes — the program runs in both.
Common Root Causes
1. A bug in your program code throws at runtime
The exception is genuinely from your code: dereferencing undefined, calling a function that doesn’t exist, or an assertion you wrote. Read the stack trace’s top frame — it names the file and line.
TypeError: config.subnets.map is not a function
at /app/index.ts:58:24
2. Missing required configuration or environment values
Reading a required config value that isn’t set throws. Config.require() and requireSecret() throw by design when the key is absent.
const config = new pulumi.Config();
// Throws "Missing required configuration variable 'dbPassword'" if unset.
const dbPassword = config.requireSecret("dbPassword");
3. An unhandled promise rejection
async work that rejects without a .catch() bubbles up as an unhandled exception. A common shape is doing an await at the top level to an API that fails (bad credentials, missing resource).
// If getAmi rejects, nothing catches it → unhandled exception.
const ami = await aws.ec2.getAmi({ owners: ["amazon"], mostRecent: true,
filters: [{ name: "name", values: ["al2023-ami-*-x86_64"] }] });
4. Throwing inside an .apply() callback
Code that runs inside output.apply(cb) executes later; if cb throws, it surfaces as an unhandled exception during deployment rather than at graph-construction time.
bucket.id.apply(id => {
// Throws if id doesn't match the expected format.
return id.split("-")[3].toUpperCase(); // undefined.toUpperCase() → TypeError
});
5. A syntax or module-resolution error at load time
A SyntaxError in TypeScript, or importing a module that isn’t installed, throws while the host is loading index.ts.
Error: Cannot find module 'aws-sdk'
Require stack: - /app/index.ts
How to Diagnose
Read the underlying trace first; then reproduce it outside Pulumi if needed.
# Re-run with verbose logging to capture the full stack trace and host output.
pulumi up --logtostderr -v=3 2> pulumi-debug.log
# Type-check the TypeScript program independently — catches many bugs early.
npx tsc --noEmit
# Confirm all imports resolve and deps are installed.
npm ls --all 2>/dev/null | grep -i "missing\|UNMET" || echo "deps look complete"
# List what config keys the stack actually has, to catch missing values.
pulumi config
pulumi config --show-secrets # be careful where you run this
# For a suspected async/API failure, run the offending call in a REPL/script
# with the same credentials to see the raw provider error.
node -e "require('@pulumi/aws'); console.log('module loads OK')"
Fixes
Read the trace and fix the throwing line: The top non-framework frame (a path into your project) is the bug. Fix the dereference, typo, or bad assumption there. For a TypeError: Cannot read properties of undefined, guard the value or fix the ordering.
// Before: assumes vpc is always present
const subnetId = vpc.privateSubnets[0].id;
// After: validate, or make the dependency explicit
if (!vpc.privateSubnets?.length) {
throw new Error("vpc.privateSubnets is empty — check the VPC component inputs");
}
const subnetId = vpc.privateSubnets[0].id;
Set the missing configuration: If the trace says a config variable is missing, set it (mark secrets as secret).
pulumi config set dbUser appuser
pulumi config set --secret dbPassword 'REDACTED'
pulumi up
Handle async rejections explicitly: Wrap top-level await work so failures produce a clear message, or move data lookups into pulumi.output(...) chains.
async function main() {
const ami = await aws.ec2.getAmi({ owners: ["amazon"], mostRecent: true,
filters: [{ name: "name", values: ["al2023-ami-*-x86_64"] }] });
return { amiId: ami.id };
}
// Surface a readable error instead of a bare rejection.
export const outputs = main().catch(err => {
throw new Error(`AMI lookup failed: ${err.message}`);
});
Fix module/syntax errors: Install the missing package or correct the import, then re-run.
npm install @pulumi/aws
npx tsc --noEmit # confirm the program compiles
pulumi up
What to Watch Out For
- The banner line is never the whole story — the actionable detail is always in the stack trace beneath it.
- Errors inside
.apply()callbacks appear at deployment time, not construction time; test that logic carefully. Config.require()throws by design — preferconfig.get()with a default when a value is genuinely optional.- An unhandled promise rejection can abort the whole run; always
.catch()top-level async work. - Run
npx tsc --noEmitin CI beforepulumi upto catch a whole class of these before they ever reach the engine.
Related Guides
- Pulumi Error: ‘Cannot read properties of undefined’ — Troubleshooting Guide
- Pulumi Error: ‘could not find any node_modules folder’ — Troubleshooting Guide
- Pulumi Error: ‘preview failed’ — Troubleshooting Guide
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.