Fix opaque "Process exited with code 1" in VS Code workspace view#9136
Fix opaque "Process exited with code 1" in VS Code workspace view#9136vhvb1989 wants to merge 3 commits into
Conversation
7adc968 to
b19aa8e
Compare
|
Azure Pipelines: Successfully started running 1 pipeline(s). 21 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
/azp run azure-dev - vscode |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
🚧 Blocked by #9140. The remaining red check ( |
The Azure Resources workspace tree resolves each application node by running `azd show --no-prompt --output json` via execAsync. When azd exits non-zero, spawnStreamAsync rejects from a ChildProcess handler with a generic "Process exited with code 1" message *before* the caller reads stderr, so the real azd error is discarded. The failure is then reported as a modal error with a "Report Issue" button, prompting users to file bugs (e.g. #9130, #9131) for routine states like not being logged in or having no environment yet. - execAsync: on non-zero exit, append the child process's stderr to the error message so callers can classify and report the real failure instead of an opaque exit code. This also makes the existing azure.yaml error classification in AzureDevShowProvider effective. - AzureDevCliApplication.getResults: suppress the error display for this background tree resolution so expected/environmental failures no longer surface a Report Issue popup. Telemetry still records them. - Add execAsync unit tests covering success, stderr-on-failure, and empty-stderr failure paths. Fixes #9130 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8907c2b4-8adc-4280-8f11-af43d905644f
The previous execAsync test spawned a real `node -e` subprocess, which failed on Windows CI: NoShell stripped the inner double quotes from the inline script (`process.stdout.write(out)` -> ReferenceError). Relying on a real process / process.execPath inside the extension host is fragile and platform-dependent. Add an optional injectable spawn function to execAsync (defaulting to the real spawnStreamAsync) and rewrite the tests to inject a fake that writes to the accumulator pipes and resolves/rejects. This exercises the real stderr-appending logic deterministically with no subprocess, so it passes identically on Linux, macOS, and Windows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8907c2b4-8adc-4280-8f11-af43d905644f
82e3535 to
304a3cd
Compare
|
Azure Pipelines: Successfully started running 1 pipeline(s). 21 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
📋 Prioritization NoteThanks for the contribution! The linked issue isn't in the current milestone yet. |
There was a problem hiding this comment.
Pull request overview
Improves VS Code workspace-view error handling for failed azd show calls.
Changes:
- Suppresses background tree-resolution error dialogs.
- Includes stderr in process-exit errors.
- Adds unit tests and release notes.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
AzureDevCliApplication.ts |
Suppresses passive resolution dialogs. |
execAsync.ts |
Appends stderr to exit errors. |
execAsync.test.ts |
Tests process output and failures. |
CHANGELOG.md |
Documents the fix. |
jongio
left a comment
There was a problem hiding this comment.
One issue on the error-surfacing change, the rest looks fine.
The new catch block in execAsync can hang for any rejection that isn't a non-zero process exit (details inline). I confirmed it against @microsoft/vscode-processutils 0.2.1: with this change an ENOENT command (azd not on PATH) never settles, where the old await spawnStreamAsync(...) rejected right away. Gating the stderr read on isChildProcessError keeps the fix for the code-1 case while letting pre-spawn and spawn-error failures rethrow.
The suppressDisplay change and CHANGELOG entry look good.
- execAsync: only append stderr for ChildProcessError (non-zero exit); rethrow pre-spawn failures (cancelled token, Windows exe-resolution) immediately so an un-ended stderr pipe can't hang execAsync. - Tests: use ChildProcessError for exit cases; add a pre-spawn regression test that guards against the hang; make the exit-error test close stderr AFTER the spawn promise rejects to reproduce the real ordering and prove execAsync waits for stderr before appending it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: bfac0afb-0a7c-4406-93f8-ee4506b494e6
| // environment yet, invalid azure.yaml) rather than an extension bug, so don't surface a | ||
| // modal error with a "Report Issue" button. The failure is still captured in telemetry, | ||
| // and azure.yaml problems are reported independently via the Problems panel. | ||
| actionContext.errorHandling.suppressDisplay = true; |
|
|
||
| suite('execAsync Tests', () => { | ||
| test('Returns stdout and stderr on success', async () => { | ||
| const { stdout, stderr } = await execAsync('cmd', [], undefined, fakeSpawn('out', 'err')); |
jongio
left a comment
There was a problem hiding this comment.
The isChildProcessError gate resolves the pre-spawn hang I flagged, and the new pre-spawn regression test (guarded by the 1s timeout) locks it in. Verified the exit-error test now closes stderr after the rejection, so it proves execAsync waits for the flushed stderr before appending it.
VSCode Extension Installation Instructions
|
Warning
Blocked by #9140 — the
azure-dev - vscodeADO pipeline currently fails for allext/vscodePRs due tonpm ci --no-optionaldropping esbuild's platform binary (unrelated to this change). GitHubbuild-testis green on all 3 OSes for this commit.Fixes #9130 (and its duplicate #9131).
Problem
Customers received an opaque error notification with a Report Issue button:
Root cause
The Azure Resources workspace tree view resolves each application node by running
azd show --no-prompt --cwd <dir> --output jsonviaexecAsync(
AzureDevCliApplication.getResults→WorkspaceAzureDevShowProvider.getShowResults).azd showexits non-zero,spawnStreamAsyncrejects from inside aChildProcessexithandler with a genericProcess exited with code 1message (hence theChildProcess.<anonymous>call stack) — beforeexecAsyncever reads the accumulatedstderr. So the real azd error (on stderr) is silently discarded, and the existing
azure.yamlerror classification ingetShowResultscan never match.getResultsdid not setsuppressDisplay, so this background tree resolution surfaced amodal error with a Report Issue prompt. Routine states (not logged in, no environment yet,
invalid
azure.yaml) therefore looked like extension bugs and got auto-reported (Process exited with code 1 #9130, Process exited with code 1 #9131).Fix
execAsync.ts— on a non-zero exit, append the child process's stderr to the thrownerror's message.
AccumulatorStream.getString()awaits the streamcloseevent, so stderr isfully flushed (no race). This surfaces the real reason and makes the existing classification in
AzureDevShowProvidereffective.AzureDevCliApplication.getResults— seterrorHandling.suppressDisplay = truefor thispassive tree resolution so expected/environmental failures no longer pop a Report Issue dialog.
Telemetry still records the failure for real triage, and
azure.yamlproblems continue to bereported via the Problems panel.
execAsyncunit tests (success, stderr-on-failure, empty-stderr failure).Validation
npm run lint✓npx tsc --noEmit✓npx cspell "src/**/*.ts" --config .vscode/cspell.yaml✓ (0 issues)npm run build(esbuild + tsc) ✓npm test(vscode-test) could not run in this environment (requires a display/Xvfb, which isunavailable). The new tests use the current Node.js executable to exercise the real
spawnStreamAsyncpath cross-platform.