Pulumi error handling: what am I missing? I have ...
# general
i
Pulumi error handling: what am I missing? I have a function that checks pre-emptively to ensure we are using the proper service account. If I include this code IN the stack, at least I see error messages but I still get a strange stack trace. >> More in thread TL;DR how do I raise an error properly, get the messages printed to the console, and not see an ugly stack trace for
RangeError: Invalid string length
?
Copy code
import { execSync } from 'node:child_process'
import { RunError } from '@pulumi/pulumi'

function enforceServiceAccount(allowedIdentity: 'inf' | 'app'): void {
  const currentAccount = execSync('gcloud config get-value account 2>/dev/null', {
    encoding: 'utf-8',
  }).trim()

  // Check if current account contains the disallowed identity
  const disallowedIdentity = allowedIdentity === 'inf' ? 'app' : 'inf'

  if (currentAccount.includes(`${disallowedIdentity}-`)) {
    // Log detailed instructions to console
    console.error(`\n❌ This stack requires the "${allowedIdentity}" service account.`)
    console.error(`Current: ${currentAccount}`)
    console.error(`\nActivate the correct account:`)
    console.error(`  cd cloud/identity && yarn gcpActivate ${allowedIdentity}\n`)

    // Throw a concise RunError for Pulumi
    throw new RunError(
      `Wrong service account: found "${disallowedIdentity}" but need "${allowedIdentity}".`,
    )
  }

  // Optionally verify the correct account is active
  if (!currentAccount.includes(`${allowedIdentity}-`)) {
    console.warn(
      `\n⚠️  WARNING: Expected "${allowedIdentity}" service account but found: ${currentAccount}`,
    )
    console.warn(`If this is not a service account, activate the "${allowedIdentity}" account:`)
    console.warn(`  cd cloud/identity && yarn gcpActivate ${allowedIdentity}\n`)
  }
}

// Enforce that this stack runs with the 'app' service account, not 'inf'
enforceServiceAccount('app')
The
preview
result is desirable (in stack), but without the stack trace:
Copy code
~/p/a/c/storage ❯❯❯ pulumi preview                                                                                                                                                                                                                                                                                                                                  ✘ 255 
Previewing update (alienfast/green)

View in Browser (Ctrl+O): <https://app.pulumi.com/alienfast/storage/green/previews/fc957836-2134-439c-8a6f-6d3db66c1d62>

     Type                 Name           Plan       Info
 +   pulumi:pulumi:Stack  storage-green  create     3 errors; 6 messages

Diagnostics:
  pulumi:pulumi:Stack (storage-green):
    06:22:00 debug  loadProjectEnv  Loading /Users/kross/projects/archetype/.env
    [dotenv@17.2.3] injecting env (14) from ../../.env -- tip: 👥 sync secrets across teammates & machines: <https://dotenvx.com/ops>

    ❌ This stack requires the "app" service account.
    Current: <mailto:inf-green@af-archetype.iam.gserviceaccount.com|inf-green@af-archetype.iam.gserviceaccount.com>
    Activate the correct account:
      cd cloud/identity && yarn gcpActivate app

    error: Wrong service account: found "inf" but need "app".
    error: Running program '/Users/kross/projects/archetype/cloud/storage/src/index.ts' failed with an unhandled exception:
    RangeError: Invalid string length
        at markNodeModules (node:internal/util/inspect:1601:21)
        at formatError (node:internal/util/inspect:1691:18)
        at formatRaw (node:internal/util/inspect:1084:14)
        at formatValue (node:internal/util/inspect:932:10)
        at Object.inspect (node:internal/util/inspect:409:10)
        at Object.defaultErrorMessage (/Users/kross/projects/archetype/node_modules/@pulumi/cmd/run/error.ts:28:21)
        at process.uncaughtHandler (/Users/kross/projects/archetype/node_modules/@pulumi/cmd/run/run.ts:449:41)
        at process.emit (node:events:520:35)
        at process.emit (/Users/kross/projects/archetype/node_modules/source-map-support/source-map-support.js:516:21)
        at process.emit.sharedData.processEmitHook.installedValue [as emit] (/Users/kross/projects/archetype/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)
    error: an unhandled error occurred: Program exited with non-zero exit code: 1

Resources:
    + 1 to create
The real problem is that if I want to reuse this function across stacks and put it in my shared common dir (with other shared resources that work), I get NO messages, just
Copy code
~/p/a/c/storage ❯❯❯ pulumi preview                                                                                                                                                                                                                                                                                                                                  ✘ 255 
Previewing update (alienfast/green)

View in Browser (Ctrl+O): <https://app.pulumi.com/alienfast/storage/green/previews/30e2cca5-65f8-406b-8b53-29453cad9580>

     Type                 Name           Plan       Info
 +   pulumi:pulumi:Stack  storage-green  create     2 errors

Diagnostics:
  pulumi:pulumi:Stack (storage-green):
    error: Running program '/Users/kross/projects/archetype/cloud/storage/src/index.ts' failed with an unhandled exception:
    RangeError: Invalid string length
        at markNodeModules (node:internal/util/inspect:1601:21)
        at formatError (node:internal/util/inspect:1691:18)
        at formatRaw (node:internal/util/inspect:1084:14)
        at formatValue (node:internal/util/inspect:932:10)
        at Object.inspect (node:internal/util/inspect:409:10)
        at Object.defaultErrorMessage (/Users/kross/projects/archetype/node_modules/@pulumi/cmd/run/error.ts:28:21)
        at process.uncaughtHandler (/Users/kross/projects/archetype/node_modules/@pulumi/cmd/run/run.ts:445:3)
        at process.emit (node:events:520:35)
        at process.emit (/Users/kross/projects/archetype/node_modules/source-map-support/source-map-support.js:516:21)
        at process.emit.sharedData.processEmitHook.installedValue [as emit] (/Users/kross/projects/archetype/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)
    error: an unhandled error occurred: Program exited with non-zero exit code: 1
TL;DR how do I raise an error properly, get the messages printed to the console, and not see an ugly stack trace for
RangeError: Invalid string length
?
How many affirmations on a Bug before it is prioritized?
l
Hey Ross, if you're checking this before any resource registration that Pulumi does then I think using
process.exit(1)
instead of the
throw new runError
will work better. It won't output the stack trace and I think it will be handled better when used as a shared module. I haven't tested it myself but I believe it should work
i
process.exit(1) is much the same.
Here is the process.exit(1) output from the shared lib
Copy code
~/p/a/c/storage ❯❯❯ pulumi preview
Previewing update (alienfast/green)

View in Browser (Ctrl+O): <https://app.pulumi.com/alienfast/storage/green/previews/d34df4f3-848a-47ee-8705-4f4bdb85bc07>

     Type                 Name           Plan     Info
     pulumi:pulumi:Stack  storage-green           2 errors

Diagnostics:
  pulumi:pulumi:Stack (storage-green):
    error: Running program '/Users/kross/projects/archetype/cloud/storage/src/index.ts' failed with an unhandled exception:
    RangeError: Invalid string length
        at markNodeModules (node:internal/util/inspect:1601:21)
        at formatError (node:internal/util/inspect:1691:18)
        at formatRaw (node:internal/util/inspect:1084:14)
        at formatValue (node:internal/util/inspect:932:10)
        at Object.inspect (node:internal/util/inspect:409:10)
        at Object.defaultErrorMessage (/Users/kross/projects/archetype/node_modules/@pulumi/cmd/run/error.ts:28:21)
        at process.uncaughtHandler (/Users/kross/projects/archetype/node_modules/@pulumi/cmd/run/run.ts:445:3)
        at process.emit (node:events:520:35)
        at process.emit (/Users/kross/projects/archetype/node_modules/source-map-support/source-map-support.js:516:21)
        at process.emit.sharedData.processEmitHook.installedValue [as emit] (/Users/kross/projects/archetype/node_modules/@cspotcode/source-map-support/source-map-support.js:745:40)
    error: an unhandled error occurred: Program exited with non-zero exit code: 1

Resources:
    1 unchanged
l
Hmmm okay, the other option could be to use
throw new Error
instead of the
throw new RunError
? I'm curious, when you ran it locally, did
process.exit(1)
exit cleanly and only output your error message minus the stack trace?
i
I also ran with
throw new Error
, same result. process.exit output is above, no error plus stack trace
l
even when you ran it as a local definition and not a shared lib?
i
Yes, local
process.exit(1)
is clean and prints the error. Similar to the github issue I linked, this isn’t very useful because we want to use this in 7 stacks.
l
Got it, one more potentially dumb question: I didn't see an
export
step for that function. Was it just not in your screenshot or is that missing?
i
I pasted in the one that I had locally.
typecheck runs etc.
We have 7 stacks with plenty of common code, in addition to a separate monorepo with more reused pulumi code.
We have multiple production apps deployed using the same base. 7 stacks per app/product
l
Understood. I see that you added to the github issue, thank you for that. It will likely have to go through that workflow as I'm not sure what the resolution is
i
Are bugs prioritized above the rest? The reason I ask is because I wasted some time on a coding error on my part, with the same exact stack trace. As you may have guessed, the coding error was in reused/common code. So, it’s not a nice to have, but a serious issue affecting DX
The only reason I figured it out was because my claude code agents got frustrated and instrumented the pulumi code itself to get to the source error. Had I not let cc churn on it I would have been stuck.
l
Got it, I can certainly understand that its frustrating. I will surface it up but unfortunately prioritization depends on many factors so hard for me to say
👍 1