$npx -y skills add pulumi/agent-skills --skill pulumi-debug-failed-operationDebug a Pulumi update or preview that failed: read the failure Pulumi already recorded, find what caused it, and fix it. Load this skill when the user asks to debug, diagnose, or fix a failed update or preview, or points at a failing pulumi up or pulumi preview. Don't load it
| 1 | # Debug a failed Pulumi operation |
| 2 | |
| 3 | A Pulumi operation has failed. Find what caused it and fix it. The user usually |
| 4 | points you at it, so start by working out which operation to debug, and confirm it |
| 5 | with the user before doing anything else. Pulumi recorded the error when the |
| 6 | operation failed, so once you know which operation it is you can read the error from |
| 7 | that record without running anything again. |
| 8 | |
| 9 | The commands below reach Pulumi Cloud with `pulumi api`, a subcommand of the Pulumi |
| 10 | CLI that you run in your shell. Each one targets a stack by the explicit |
| 11 | `{orgName}/{projectName}/{stackName}` path you pass it, so you do not need that |
| 12 | stack selected locally to read its record. Selecting the stack matters later, when |
| 13 | you go to apply a fix. |
| 14 | |
| 15 | ## Start from the operation the user gave you |
| 16 | |
| 17 | The user usually supplies the operation as a set of fields: the org, project, stack, |
| 18 | and update version (or preview id) — most often stated in prose, for example "debug |
| 19 | update 161 of vvm-dev". You need these to address the API: `{orgName}`, |
| 20 | `{projectName}`, `{stackName}`, and the version or preview id. |
| 21 | |
| 22 | Fill any missing field from context. Take the org, project, or stack from the |
| 23 | currently selected stack (`pulumi stack --show-name`, `pulumi stack ls`) or |
| 24 | `Pulumi.yaml`. A missing version means the most recent update on that stack. |
| 25 | |
| 26 | Briefly confirm which operation you landed on, its version or preview id and the |
| 27 | stack, before reading further. Keep it lightweight; they already told you. |
| 28 | |
| 29 | ## Read what failed |
| 30 | |
| 31 | A failed update and a failed preview both record engine events, and the error is in |
| 32 | the diagnostic messages inside those events. Using the fields you settled on above, |
| 33 | fetch the events and pull the messages out. |
| 34 | |
| 35 | For a failed update, use the `update` path with the version number: |
| 36 | |
| 37 | ``` |
| 38 | pulumi api /api/stacks/{orgName}/{projectName}/{stackName}/update/<version>/events \ |
| 39 | | jq -r '.events[].diagnosticEvent | select(. != null) | "[\(.severity)] \(.message)"' \ |
| 40 | | sed 's/<{%reset%}>//g' |
| 41 | ``` |
| 42 | |
| 43 | For a failed preview, use the `preview` path with the preview id: |
| 44 | |
| 45 | ``` |
| 46 | pulumi api /api/stacks/{orgName}/{projectName}/{stackName}/preview/<preview-id>/events \ |
| 47 | | jq -r '.events[].diagnosticEvent | select(. != null) | "[\(.severity)] \(.message)"' \ |
| 48 | | sed 's/<{%reset%}>//g' |
| 49 | ``` |
| 50 | |
| 51 | Read every message, not only the ones tagged `severity == "error"`. A provider |
| 52 | error carries that `error` tag, but a program error, which is the common case when |
| 53 | a preview fails, arrives as a stderr diagnostic tagged `info#err`. The trailing |
| 54 | `sed` strips terminal color codes that Pulumi embeds in the text, which otherwise |
| 55 | show up as `<{%reset%}>`. |
| 56 | |
| 57 | ## Find the cause and where the fix belongs |
| 58 | |
| 59 | An operation can fail with errors from more than one resource, so read all of the |
| 60 | diagnostics first, then work through each error. Trace every error back to the |
| 61 | resource that raised it (its URN and type), to where that resource is declared in |
| 62 | the program, and to the inputs that feed it. |
| 63 | |
| 64 | The error text tells you what kind of problem it is, and that points to where the |
| 65 | fix belongs. A Pulumi fix lands in one of three places, and naming the right one |
| 66 | keeps you from editing code that was never the problem. |
| 67 | |
| 68 | - **The program.** The code is wrong: a bad reference, a wrong type, an input the |
| 69 | provider rejected, or a value used before it had resolved. This is what a failed |
| 70 | preview usually reports, because the plan could not be built. Fix it by editing |
| 71 | the code. |
| 72 | - **The state.** The code is correct, but the stored state and the real cloud |
| 73 | resources disagree. Reconcile drift with `pulumi refresh`, and bring a resource |
| 74 | that already exists outside the state under management with `pulumi import` |
| 75 | rather than recreating it. Note that an operation which failed partway through |
| 76 | applying may have already changed some resources, so check the current state |
| 77 | before you decide. |
| 78 | - **The environment.** The problem is outside Pulumi: credentials, permissions, |
| 79 | OIDC, or a quota. Fix the role, the ESC environment, or the capacity that the |
| 80 | provider rejected, rather than the resource code. |
| 81 | |
| 82 | ## Fix the cause |
| 83 | |
| 84 | Make the smallest change that addresses the root cause. How you confirm the fix, |
| 85 | and how you deliver it, whether as a local edit or as a pull request, follow your |
| 86 | mode's workflow, not this skill. |
| 87 | |
| 88 | ## If the user didn't say which operation |
| 89 | |
| 90 | When the user gives you nothing to go on, debug their most recent operation on the |
| 91 | stack. The update list does not record who ran each update, so find it through the |
| 92 | API: |
| 93 | |
| 94 | 1. Run `pulum |