Troubleshooting Pulumi in CI/CD
Every CI/CD system runs Pulumi the same way under the hood, so the failures you hit in an automated pipeline tend to fall into the same handful of categories regardless of which system you use. This guide walks through the steps of a typical Pulumi pipeline run and the class of failure tied to each one, so you can narrow down where a build is going wrong and what to check.
Overall requirements
To run a pulumi preview or pulumi up in a pipeline, the build agent needs all of the following:
- A way to authenticate with your backend — a Pulumi access token when using Pulumi Cloud.
- A stack that the pipeline will update, created ahead of time.
- The Pulumi CLI available on the system
PATH. - The language runtime and build tools for your Pulumi program (more on this below).
- Your program’s dependencies and resource provider plugins, installed before a preview or update.
- Valid cloud provider credentials with permission to manage your resources.
The type of failure you see is almost always traceable to one of these. The sections below cover each in turn.
Pulumi access token
When Pulumi detects that it’s running inside a CI/CD system, it skips the interactive pulumi login prompt and authenticates non-interactively instead. With Pulumi Cloud as your backend, it reads the access token from the PULUMI_ACCESS_TOKEN environment variable.
What to check when authentication fails:
- The token is exposed to the pipeline as an environment variable named exactly
PULUMI_ACCESS_TOKEN. Store it as a secret — most CI/CD systems can mark an environment variable as sensitive, and your access token is a sensitive value. - The environment variable is actually in scope for the job or step that runs the
pulumicommand. Many CI/CD systems reset the environment between jobs or stages, so a variable set in one job may not be visible in another. - The pipeline can reach the secret. Several systems restrict secrets to specific branches or environments — confirm the branch and job running Pulumi are allowed to read it.
- Prefer an organization or team access token over a personal one, so the pipeline’s identity isn’t tied to an individual.
To avoid storing a long-lived secret at all, use OpenID Connect (OIDC): the pipeline exchanges a short-lived token issued by your CI/CD system for a temporary Pulumi access token. Pulumi ESC can then supply cloud credentials and configuration the same way to both pipelines and developer machines.
Stack name
A stack is a specific, configurable instance of your infrastructure. A pipeline updates an existing stack — it does not create one — so the stack must already exist in the correct organization, created beforehand with pulumi stack init.
What to check when a pulumi command can’t find or access your stack:
- The account behind your access token has access to the stack. A token without access produces 404s from Pulumi Cloud. Confirm by signing in to Pulumi Cloud with the same account and navigating to the stack.
- Pass a fully qualified stack name to
pulumicommands. A fully qualified stack name has the form<organization>/<project>/<stack>— for example, a stack namedproductionin thepulumiorganization andslack-botproject ispulumi/slack-bot/production. Pulumi can infer the project from yourPulumi.yaml, so the fully qualified form is optional, but using it removes any ambiguity about which stack a pipeline targets. - The
pulumicommand runs from the directory containing your project’sPulumi.yaml. If your program lives elsewhere, pass--cwd— see the global flags supported by everypulumicommand. - The stack’s configuration file sits alongside
Pulumi.yaml. For a stack namedproduction,Pulumi.production.yamlmust be in the same directory asPulumi.yaml.
Installing the Pulumi CLI
The build agent needs the Pulumi CLI on its PATH. Several CI/CD systems have a native extension that installs and runs the CLI for you:
- Azure Pipelines task extension — see the Azure DevOps guide.
- GitHub Actions —
pulumi/actionsandpulumi/action-install-pulumi-cli; see the GitHub Actions guide. GitHub-hosted runners ship the Pulumi CLI pre-installed, so an explicit install step is only needed to pin a specific version. - CircleCI orb — see the CircleCI guide.
If your system has no native extension, add an inline script step to install the CLI manually.
What to check when pulumi isn’t found:
- The CLI is available in the same step that runs
pulumicommands. The official install script addspulumito thePATHof the current environment, but that change does not always carry across steps. - This is especially common with container-based pipelines: a container’s filesystem and environment often don’t persist between steps, so installing the CLI in one step and calling it in another won’t work. Some systems let you define a reusable setup step or template to avoid repeating the install. Running Pulumi inside the
pulumi/pulumicontainer image — which already includes the CLI and every language runtime — sidesteps the problem entirely.
Build tools
Pulumi invokes the build tool for your project’s runtime. If the pipeline is missing that toolchain, Pulumi can’t run your program. For example, a nodejs project needs a supported version of Node.js along with the package manager you use (npm, yarn, or pnpm). The requirements differ by language — see the page for your language for the specific runtime and tooling it needs.
What to check when a build fails before Pulumi reaches your resources:
- Your project’s runtime and build tools are installed on the build agent. Most CI/CD systems offer a built-in way to install a specific language version — GitHub Actions, for instance, provides
actions/setup-node,actions/setup-python,actions/setup-go, andactions/setup-dotnet. - For container-based pipelines, consider the
pulumi/pulumiimage, which bundles the CLI and every supported language runtime.
Restoring dependencies
Every Pulumi program depends on at least the Pulumi SDK, and those dependencies — along with the resource provider plugins your program uses — must be present before Pulumi runs a preview or update.
What to check when a run fails on missing packages or plugins:
- The simplest way to restore everything is
pulumi install, which installs both your program’s dependencies and the required plugins in a single step, for any runtime. Run it beforepulumi previeworpulumi up. - If you restore dependencies with your language’s own package manager instead, note that the behavior varies by runtime: for
dotnetandgoprojects, dependencies are restored automatically when you runpulumi previeworpulumi up, whilenodejsandpythonprojects need an explicit restore step. - A
.NETproject that pulls packages from a private feed is an exception to automatic restore. Make sure the private feed is reachable from the pipeline, or use a pre-built binary so the solution doesn’t need to be rebuilt. If you use a pre-built binary, install the necessary plugins manually withpulumi plugin install. - If you cache dependencies, cache the Pulumi plugins too. Installing the Pulumi SDK triggers a post-install step that downloads resource provider plugins from Pulumi’s CDN. Caching only your language packages leaves those plugins to be re-downloaded — or missing — on each run. Note that plugin caches can grow large depending on how many providers you use, and some CI/CD systems cap cache size.
- When a run fails for reasons you can’t pin down, clear all caches and restore dependencies from scratch to rule out a stale cache.
Cloud provider credentials
Cloud provider credentials are another common point of failure. Credential errors usually fall into two buckets: the wrong credentials (wrong account, mismatched keys) or credentials whose access scope is too narrow to create the resources your program declares.
What to check when resource operations fail with authentication or authorization errors:
- The credentials are supplied to Pulumi through a mechanism the provider supports. Environment variables work in nearly all cases. Some providers also support authentication through their own CLI — the Azure provider, for example, can use the Azure CLI’s session, but only if that CLI is itself authenticated with an account that has the right role and subscription.
- The step running the
pulumicommand can actually read the credential variables. As with the Pulumi access token, secrets are often scoped to specific jobs, stages, or branches, and environments can reset between jobs. - There are no typos in the credential environment variable names.
Refer to each provider’s page in the Pulumi Registry for the exact environment variables it expects.
If you use Pulumi Cloud, Pulumi ESC is an alternative to storing static cloud keys in your CI/CD system: it can supply cloud provider credentials to your pipeline dynamically, including short-lived credentials issued through OIDC.
Still need help?
If none of the above resolves your issue, the Pulumi Community Slack is a great place to ask — signup is free, and Pulumi team members are active there alongside other community members. To report a bug, see the guide for filing issues so it lands in the right repository.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.