Answer the Exact Question First
1. Rollback support: Pulumi does not automatically roll back a partially applied stack after a retry. Each resource apply is independent, and the state file only records the resources that succeeded.
2. Provider‑level idempotency metadata: Providers can expose idempotency information (e.g., idempotency keys, “already exists” responses), but Pulumi does not enforce a generic contract to interpret that metadata during retries.
3. Treating one failure as a stack failure: There is no built‑in flag to make a single resource failure abort the entire stack. You can achieve this by serialising applies (e.g., pulumi config set pulumi:parallel 1) or by writing a pre‑apply script that checks for failures and exits early.
Likely Explanation
When Pulumi encounters a retryable error from a provider, the engine simply re‑issues the same provider operation. It trusts that the provider’s API is idempotent, so a second call with the same arguments should not create a duplicate resource. If the provider is not truly idempotent, duplicate resources can appear. Pulumi’s state file is updated only after a resource reports success, so a partially applied stack can leave orphaned resources that were created before the failure.
Confirmed Facts (from the research brief)
- Engine retries rely on provider idempotency; no generic metadata enforcement.
- No automatic rollback of partially applied stacks.
- No flag to treat a single resource failure as a stack failure.
- Sequential apply (maxParallel=1) reduces concurrency but surfaces failures immediately.
Steps Needed for This Case
- Verify provider idempotency. Test creating the same resource twice using the provider’s API or Pulumi. If the second call returns an “already exists” response or uses an idempotency key, you can rely on it.
- Enable debug logging. Run
pulumi up --debug to see when retries happen and what the provider replies.
- Check the state file. After a failed
pulumi up, export the state with pulumi stack export --file stack.json and inspect which resources are marked as created versus pending.
- Serialise applies if needed. If you want a failure to abort the stack, set
pulumi config set pulumi:parallel 1 or use a custom pre‑apply script that exits on the first error.
- Consider cleanup scripts. For providers that are not idempotent, write a post‑apply cleanup that deletes orphaned resources if a retry fails.
Missing Diagnostic Detail
Do you know whether the provider you are using supports idempotency keys or returns a standard “already exists” response for the resource type you are creating? This information can change the recommendation for how to guard against duplicate writes.