From f347d9a58afdfcc99c98c3cd8f9327fca0a26812 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:49:38 +1000 Subject: [PATCH] fix(desktop-wsl): drop DefaultUid=0 first-run gate, --user root bypasses OOBE Verified with live probes: 'wsl -d Ubuntu-24.04 --user root -- echo OK' succeeds on a distro whose registry DefaultUid is still 0 (OOBE never ran). The prior hang symptom was from invoking wsl WITHOUT --user when DefaultUid=0, which triggers the interactive 'Create a default UNIX user account' prompt. With --user root explicit in wslArgs the OOBE hook is skipped and resolveWslOpencode finds /root/.opencode/bin/opencode etc. Remove the overly aggressive first-run gate from spawnWslSidecar; the registry probe helpers stay in wsl.ts for future diagnostic use. 20s timeout + failure logging remain as safety nets for true wsl.exe wedges. --- packages/desktop-electron/src/main/server.ts | 28 +++++++------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/packages/desktop-electron/src/main/server.ts b/packages/desktop-electron/src/main/server.ts index cf2e5e3491..8bfd19ef20 100644 --- a/packages/desktop-electron/src/main/server.ts +++ b/packages/desktop-electron/src/main/server.ts @@ -5,7 +5,7 @@ import { app } from "electron" import { DEFAULT_SERVER_URL_KEY } from "./constants" import { getUserShell, loadShellEnv } from "./shell-env" import { getStore } from "./store" -import { checkWslDistroFirstRun, type WslCommandLine, resolveWslOpencode, wslArgs } from "./wsl" +import { type WslCommandLine, resolveWslOpencode, wslArgs } from "./wsl" export type HealthCheck = { wait: Promise } @@ -83,23 +83,15 @@ export async function spawnWslSidecar( distro: string, opts: { onLine?: (line: WslCommandLine) => void; healthTimeoutMs?: number } = {}, ): Promise { - // Gate on the registry state BEFORE any wsl.exe invocation. If the - // distro still has DefaultUid=0 it means the interactive first-run - // "Create a default UNIX user account" prompt never completed, and - // every wsl.exe -d ... call will silently block on stdin - // forever (we verified: Ubuntu-24.04 hangs on both -- echo and - // --user root -- echo in this state). Fail fast with a clear message - // so the controller can surface it to the user. - const firstRun = await checkWslDistroFirstRun(distro) - if (firstRun.status === "not-installed") { - throw new Error(`WSL distro ${distro} is not installed`) - } - if (firstRun.status === "needs-first-run") { - throw new Error( - `WSL distro ${distro} has not completed first-run setup. Open a terminal and run 'wsl -d ${distro}' to create a default UNIX user, then retry.`, - ) - } - + // Every wsl.exe invocation below goes through wslArgs which injects + // `--user root`. That matters even when a distro has DefaultUid=0 + // (i.e. the interactive first-run user account setup never ran): + // explicit --user root bypasses the OOBE hook that would otherwise + // prompt on stdin, so we can resolve opencode and spawn the sidecar + // without any machine-wide first-run handshake. The earlier Ubuntu + // hang was caused by invoking without --user (default uid 0 triggers + // OOBE), not by the registry state itself. We still have a 20s + // timeout in runCommand as a safety net for true wsl.exe wedges. const opencode = await resolveWslOpencode(distro) if (!opencode) throw new Error(`OpenCode is not installed in ${distro}`)