fix(packaged): swallow EPIPE in console echo to stop main-process crash - #7521
fix(packaged): swallow EPIPE in console echo to stop main-process crash#7521lorenzozanee wants to merge 1 commit into
Conversation
Packaged Electron on Windows has no controlling terminal, so process.stdout is detached and the first console.info from did-start-loading throws EPIPE from inside Writable.write. Wrap console echo in safeEcho that swallows only EPIPE/ERR_STREAM_DESTROYED when the structured code equals those values, and install an async stdio error guard for the nextTick error path; the desktop file logger still records the event, non-harmless errors rethrow. Fixes nexu-io#6964
|
Thanks @lorenzozanee — this is a focused packaged-startup fix, and the logging/test split makes the intent easy to follow. I’m routing the normal triage now. One quick housekeeping ask: please tick the Surface area checklist — this reads like |
nettee
left a comment
There was a problem hiding this comment.
@lorenzozanee I found one blocking startup-order issue in the new stream guard. The focused logging tests and full packaged checks pass locally, but the guard is installed after an unguarded first-launch console path, so the reported packaged startup crash can still occur.
🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.| // safeEcho's try/catch only covers a *synchronous* throw. It does not | ||
| // cover this failure mode: verified live on a packaged Windows build | ||
| // where safeEcho alone did not stop the crash. See installStdioErrorGuard. | ||
| installStdioErrorGuard([process.stdout, process.stderr]); |
There was a problem hiding this comment.
Blocking: This installs the guard too late for packaged startup. apps/packaged/src/index.ts calls inspectExistingDesktopForLauncher(...) with the raw console before createPackagedDesktopLogger() runs. On the normal first launch, the desktop IPC socket is absent, so requestJsonIpc rejects and inspectExistingDesktopForLauncher logs logger.info("[open-design launcher] inspect-unavailable ...") before this listener exists. That raw console.info writes to detached stdout and can emit the same EPIPE this PR is meant to prevent, so the app may still crash before reaching the guarded renderer lifecycle call.
Install installStdioErrorGuard before launcher inspection (and avoid installing duplicate listeners), or route every pre-logger diagnostic through a guarded bootstrap logger; add a first-launch/no-terminal regression test for this sequence.
|
@lorenzozanee @nettee's blocking review on this head looks like the right next step to address: the stdio guard needs to cover the pre-logger launcher-inspection path as well, and the first-launch/no-terminal regression path still needs test coverage. Once that startup-order gap is fixed, we can take another look. |
Fixes #6964
Why
Packaged Electron on Windows launches without a terminal, so the first
console.infofromdid-start-loadingthrowsEPIPEinsideWritable.writeand crashes the main process with an uncaught exception. The logger already writes to the desktop file but the stdout echo had no guard, so every default launch showed the native crash dialog.What users will see
Before the dialog appeared on every packaged launch without a terminal and the app exited. After it stays running and the event is recorded only in the desktop log file. No API, env var or install layout change.
Surface area
apps/weborapps/desktop(including Electron menu bar)odsubcommand or flag, newtools-dev/tools-packflag, or newOD_*env var/api/*endpoint, new SSE event, or changed shape inpackages/contractsskills/,design-systems/,design-templates/, orcraft/, or change to the skills protocolTRANSLATIONS.mdfor the locale workflow)package.json(dependenciesordevDependencies); workspace-packagepackage.jsonfiles are out of scope. Include a paragraph on what we get vs. what bytes we ship (seeCONTRIBUTING.md→ Code style)Screenshots
Not applicable — the bug was a native crash dialog; the fix restores “no dialog” with the same main window.
Bug fix verification
apps/packaged/tests/logging.test.tsmain, green on this branch: the new EPIPE guard cases fail without the wrapper and pass with it.Validation
pnpm --filter @open-design/desktop build && pnpm --filter @open-design/packaged exec tsc -p tsconfig.json --noEmit && pnpm --filter @open-design/packaged exec tsc -p tsconfig.tests.json --noEmit && pnpm --filter @open-design/packaged exec vitest run -c vitest.config.ts tests/logging.test.ts— 29/29, typecheck clean,git diff --checkclean.Reviewers: @mrcfps @AmyShang-alt