Skip to content

fix: app:pack aborts when Node writes process warnings to api-mesh stderr - #931

Open
raj-prince587 wants to merge 1 commit into
adobe:masterfrom
raj-prince587:fix/api-mesh-node-warnings-break-app-pack
Open

fix: app:pack aborts when Node writes process warnings to api-mesh stderr#931
raj-prince587 wants to merge 1 commit into
adobe:masterfrom
raj-prince587:fix/api-mesh-node-warnings-break-app-pack

Conversation

@raj-prince587

Copy link
Copy Markdown

Description

createDeployYamlFile treats any output on the aio api-mesh get --json child's stderr as a fatal error:

if(stderr){thrownewError(stderr)}

Node process warnings go to stderr while the command still exits 0. On Node 22 the punycode deprecation (DEP0040) is emitted on virtually every aio invocation, so a successful mesh lookup aborts app:pack, surfacing the deprecation notice as the error.

Importantly, the if (stderr) throw is not redundant and is deliberately kept: it is how the "no mesh" case is detected, because api-mesh:get reports that via this.error(msg, { exit: false }) — which writes to stderr and exits 0. So instead of removing the check, this PR keeps it and removes only the noise:

  • pass NODE_NO_WARNINGS: '1' to the child, suppressing Node process warnings at the source. NODE_NO_WARNINGS is used rather than NODE_OPTIONS so that a user-set NODE_OPTIONS is preserved (execa merges env with process.env by default).
  • strip any residual (node:NNN) … / (Use `node --trace-…`) lines via a small stripNodeWarnings helper, as a backstop for warnings arriving from a wrapper or --require preload.

Behaviour is otherwise unchanged — genuine api-mesh errors still abort app:pack exactly as before.

Secondary fix in the same block

if(err?.message.includes('Error: Unable to get mesh config.')){

The optional chaining stops one level short: a thrown value with no message (a non-Error throw, or an execa error carrying output only on stderr) raises TypeError: Cannot read properties of undefined (reading 'includes') inside the catch, masking the original failure. It now inspects messageandstderr, so a "no mesh" report is recognised however it arrives, and anything unrecognised is rethrown untouched.

console.error(err) is replaced with aioLogger.debug — it bypassed the logger used everywhere else in the file and double-reported, since err is rethrown on the next line.

The 'Error: ' prefix was also dropped from the matched substring so the check doesn't depend on oclif's error styling.

Related Issue

Fixes#930

Motivation and Context

app:pack is currently unusable on Node 22 for any project where the api-mesh plugin is installed, which is the default in recent @adobe/aio-cli releases. The failure is confusing because the reported error is a deprecation warning rather than anything to do with packaging.

How Has This Been Tested?

npx jest -c jest.config.js test/commands/app/pack.test.js35 passed, with pack.js at 100% statements/branches/functions/lines (the repo's global threshold). npx eslint src test is clean.

One existing test is updated. It asserted the TypeError above as expected behaviour:

awaitexpect(command.createDeployYamlFile(extConfig)).rejects.toEqual(TypeError('Cannot read properties of undefined (reading \'includes\')'))

The mocked throw carries stderr: 'Error: Unable to get mesh config. No mesh found for Org' — a "no mesh" report — so it now asserts that the no-mesh deploy.yaml fixture is written instead of the command crashing.

Three tests are added:

  • api-mesh stderr containing only Node process warnings → mesh config still read, and NODE_NO_WARNINGS asserted on the execa options
  • a real error mixed in with Node warnings → warning stripped, real error still surfaced
  • a thrown value with neither message nor stderr → original value rethrown, no TypeError

The existing api-mesh service is unavailable and no api-mesh tests pass unmodified, which is the main guard that error semantics are unchanged.

Verified end-to-end against a real App Builder project on Node v22.22.2: before the change app:pack aborted with the DEP0040 notice; after it, the mesh lookup no longer misreports the warning as a failure.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

One question for maintainers

Should a genuine api-mesh failure abort app:pack at all? meshConfig is optional in deploy.yaml, yet an unrelated auth/org problem currently fails the entire packaging step even for apps with no mesh. I hit this with User does not belong to the organization. on a project that doesn't use api-mesh — under --json, oclif serialises that to {"error":{"oclif":{"exit":2}}}, so the message needed for classification is lost entirely.

I've deliberately left that behaviour alone here to keep this PR a pure bug fix. Happy to follow up with a separate PR making the lookup non-fatal (warn and continue) if that's the direction you'd prefer.

🤖 Generated with Claude Code

…derr
`createDeployYamlFile` treats any output on the `aio api-mesh get --json`
child's stderr as a fatal error. Node process warnings (e.g. DEP0040, the
punycode deprecation emitted on Node 22) are written to stderr while the
command exits 0, so `app:pack` aborts on a successful mesh lookup with the
deprecation notice presented as the error.
The stderr channel is still used to detect the "no mesh found" case, since
the api-mesh plugin reports it via `this.error(msg, { exit: false })` which
writes to stderr and exits 0. Rather than removing that check, Node process
warnings are suppressed in the child via NODE_NO_WARNINGS and any that still
reach stderr are stripped before the check. NODE_NO_WARNINGS is used instead
of NODE_OPTIONS so a user-set NODE_OPTIONS is preserved.
Also fixes an unguarded property access in the same catch block: `err?.message`
stops one level short, so a thrown value without a `message` (a non-Error
throw, or an execa error carrying output only on `stderr`) raised a TypeError
inside the catch and masked the original failure. The existing test asserted
that TypeError as expected behaviour; it now asserts that the "no mesh"
message on `stderr` is recognised. Error details now go to aioLogger.debug
instead of console.error, which double-reported since `err` is rethrown.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@raj-prince587
raj-prince587 marked this pull request as ready for review August 7, 2026 08:46
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app:pack aborts when Node writes process warnings to api-mesh stderr

2 participants

@raj-prince587@rupak18th