Skip to content

Commit c87d304

Browse files
Fix: Show error messages in UI when environment creation fails (#933)
## Problem When Python environment creation fails (e.g., due to executables blocked by group policy or missing dependencies), users receive no feedback in the main UI. The operation silently fails, leaving users confused about what went wrong. Errors are only logged to the output channel, which most users never check. Example from issue #XXX: ``` 2025-10-09 13:28:38.836 [info] Running: uv --version 2025-10-09 13:28:38.838 [error] Failed to create virtual environment: Error: spawn UNKNOWN ``` The user sees nothing in the UI - no error dialog, no notification, no indication that the operation failed. ## Root Cause The `child_process.spawn()` calls in the environment creation code lacked `error` event handlers. When spawning a process fails (before it can even exit with a non-zero code), Node.js emits an `error` event on the child process. Without a handler for this event, the error was caught generically, logged, but never displayed to the user. Additionally, even when errors were properly caught and stored in the `CreateEnvironmentResult` object, the calling code only checked for successful creation (`if (result?.environment)`) without a corresponding check to display errors when creation failed. ## Solution This PR adds two-level error handling: ### 1. Spawn Error Handlers (Low Level) Added `proc.on('error', ...)` handlers to catch spawn failures immediately: - `runUV()` in `src/managers/builtin/helpers.ts` - `runPython()` in `src/managers/builtin/helpers.ts` - `_runConda()` in `src/managers/conda/condaUtils.ts` These handlers log the error and reject the promise with a descriptive message. ### 2. User Error Display (High Level) Added error message display when environment creation fails: - `venvManager.ts`: Check `result?.envCreationErr` and call `showErrorMessage()` - `condaEnvManager.ts`: Add `showErrorMessage()` in catch block All error messages use localized strings via `l10n.t()` and include the actual error details. ## Example **Before this fix:** ```typescript // User clicks "Create Environment" // Process spawn fails with UNKNOWN error // User sees: (nothing - operation appears to do nothing) ``` **After this fix:** ```typescript // User clicks "Create Environment" // Process spawn fails with UNKNOWN error // User sees: "Failed to create virtual environment: Error spawning uv: spawn UNKNOWN" ``` ## Impact - Users now receive clear error messages in the UI when environment creation fails - Error messages include the actual failure reason (spawn errors, permission issues, etc.) - Both venv and conda environment managers properly report failures - Errors are still logged to the output channel for debugging - No impact on successful operations ## Testing - ✅ Code compiles successfully with `npm run compile` - ✅ Linter passes with `npm run lint` - ✅ Changes follow existing code patterns and use proper localization - Manual testing recommended for: - Executables blocked by group policy (original issue scenario) - Missing Python/UV/conda installations - Invalid environment names or paths - Permission errors Fixes #XXX <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[Python Environments] No report of failure when environment is not created</issue_title> > <issue_description> > Type: <b>Bug</b> > > <!-- Please describe the issue you're experiencing --> > When I run the command for creating a Python virtual environment, nothing happens. No env is created, but there are no error-messages either. > > If I run the traditional command myself, in the terminal (python -m venv .venv), I get an error-message, saying the program is blocked by group policy (WinError 1260). Maybe that is why it is not working when doing it from VS Code, but in that case, there should be some kind of error-message. > > UPDATE: Another error happened that showed up in the User Interface, and offered to let me look into the logs, When I got there, I see that there are log-entries for all my retrys of creating the virtual environment. So the problem is maybe twofold: > > 1) it doesn't work (probably because of policies on my employers computers) > 2) it doesn't give any feedback in the main UI that the operation failed > > This is how it shows in the log when I use the option "Quick Create": > > ``` > 2025-10-09 13:28:38.836 [info] Running: uv --version > 2025-10-09 13:28:38.838 [error] Failed to create virtual environment: Error: spawn UNKNOWN > ``` > > <!-- The following information was automatically generated --> > > <details> > <summary>Environment Information</summary> > > ``` > Extension Version: 1.8.0 > Python Extension Version: 2025.14.0 > > Registered Environment Managers (2): > - ms-python.python:system (Global) > - ms-python.python:venv (venv) > > Total Available Environments: 1 > Environment Details: > 1. Python 3.13 (3.13.8.final.0) - C:\Users\stsk\AppData\Local\Microsoft\WindowsApps\python3.13.exe > > Python Projects (1): > 1. c:\python > Environment: Python 3.13 > > Extension Settings: > Default Environment Manager: ms-python.python:venv > Default Package Manager: ms-python.python:pip > Auto-activation is "command". Activation based on first 'py-env.terminal.autoActivationType' setting which is 'command' and 'python.terminal.activateEnvironment' if the first is undefined which is 'true'. > > ``` > > </details> > > Extension version: 1.8.0 > VS Code version: Code 1.104.3 (385651c938df8a906869babee516bffd0ddb9829, 2025-10-02T12:30:51.747Z) > OS version: Windows_NT x64 10.0.26100 > Modes: > > <details> > <summary>System Info</summary> > > |Item|Value| > |---|---| > |CPUs|Intel(R) Core(TM) Ultra 5 125U (14 x 2688)| > |GPU Status|2d_canvas: enabled<br>direct_rendering_display_compositor: disabled_off_ok<br>gpu_compositing: enabled<br>multiple_raster_threads: enabled_on<br>opengl: enabled_on<br>rasterization: enabled<br>raw_draw: disabled_off_ok<br>skia_graphite: disabled_off<br>trees_in_viz: disabled_off<br>video_decode: enabled<br>video_encode: enabled<br>vulkan: disabled_off<br>webgl: enabled<br>webgl2: enabled<br>webgpu: enabled<br>webnn: disabled_off| > |Load (avg)|undefined| > |Memory (System)|15.47GB (0.41GB free)| > |Process Argv|C:\\Users\\stsk\\Documents\\Archi\\scripts\\examples\\Anonymize.ajs --crash-reporter-id e2e5a566-bed1-48e9-b34d-3d6701776fa6| > |Screen Reader|no| > |VM|0%| > </details><details> > <summary>A/B Experiments</summary> > > ``` > vsliv368cf:30146710 > pythonvspyt551:31249599 > binariesv615:30325510 > nativeloc1:31344060 > dwcopilot:31170013 > dwoutputs:31242946 > copilot_t_ci:31333650 > e5gg6876:31282496 > pythonrdcb7:31342333 > usemplatestapi:31297334 > aj953862:31281341 > cs4_fixed:31391938 > nes-set-on:31351930 > 6abeh943:31336334 > envsactivate1:31353494 > 0cj2b977:31352657 > gendocstringt:31395207 > cloudbuttont:31379625 > todos-1:31390405 > treatment_gpt5applypatchexclusively:31398171 > 3efgi100_wstrepl:31382709 > trigger-command-fix:31379601 > cmp-cht-code-treat-node-fetcher:31397680 > auto_model_enabled:31385282 > grok-v2-prompt:31398332 > use-responses-api:31390855 > 4c5ff9_b:31397103 > > ``` > > </details> > > <!-- generated by issue reporter --></issue_description> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > <comment_new><author>@eleanorjboyd</author><body> > Yes great point, there should be error messages added when create environment (either quick create or regular create) fails.</body></comment_new> > </comments> > </details> Fixes #920 <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: eleanorjboyd <[email protected]>
1 parent 7d52871 commit c87d304

File tree

4 files changed

+24
-0
lines changed

4 files changed

+24
-0
lines changed

src/managers/builtin/helpers.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ export async function runUV(
3838
reject(new CancellationError());
3939
});
4040

41+
proc.on('error', (err) => {
42+
log?.error(`Error spawning uv: ${err}`);
43+
reject(new Error(`Error spawning uv: ${err.message}`));
44+
});
45+
4146
let builder = '';
4247
proc.stdout?.on('data', (data) => {
4348
const s = data.toString('utf-8');
@@ -72,6 +77,12 @@ export async function runPython(
7277
proc.kill();
7378
reject(new CancellationError());
7479
});
80+
81+
proc.on('error', (err) => {
82+
log?.error(`Error spawning python: ${err}`);
83+
reject(new Error(`Error spawning python: ${err.message}`));
84+
});
85+
7586
let builder = '';
7687
proc.stdout?.on('data', (data) => {
7788
const s = data.toString('utf-8');

src/managers/builtin/venvManager.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,11 @@ export class VenvManager implements EnvironmentManager {
230230
}`,
231231
);
232232
}
233+
} else if (result?.envCreationErr) {
234+
// Show error message to user when environment creation failed
235+
showErrorMessage(
236+
l10n.t('Failed to create virtual environment: {0}', result.envCreationErr),
237+
);
233238
}
234239
return result?.environment ?? undefined;
235240
} finally {

src/managers/conda/condaEnvManager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ export class CondaEnvManager implements EnvironmentManager, Disposable {
191191
return result;
192192
} catch (error) {
193193
this.log.error('Failed to create conda environment:', error);
194+
showErrorMessage(
195+
l10n.t('Failed to create conda environment: {0}', error instanceof Error ? error.message : String(error)),
196+
);
194197
return undefined;
195198
}
196199
}

src/managers/conda/condaUtils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ async function _runConda(
212212
deferred.reject(new CancellationError());
213213
});
214214

215+
proc.on('error', (err) => {
216+
log?.error(`Error spawning conda: ${err}`);
217+
deferred.reject(new Error(`Error spawning conda: ${err.message}`));
218+
});
219+
215220
let stdout = '';
216221
let stderr = '';
217222
proc.stdout?.on('data', (data) => {

0 commit comments

Comments
 (0)