Skip to content

fix(css): retry scss compilation when the embedded sass compiler fails to spawn - #23375

Open
lopno wants to merge 1 commit into
vitejs:mainfrom
lopno:fix/scss-respawn-dead-embedded-compiler
Open

fix(css): retry scss compilation when the embedded sass compiler fails to spawn#23375
lopno wants to merge 1 commit into
vitejs:mainfrom
lopno:fix/scss-respawn-dead-embedded-compiler

Conversation

@lopno

@lopno lopno commented Aug 26, 2026

Copy link
Copy Markdown

Description

Fixes #23374. Related: #20825 (closed, locked).

When sass-embedded's compiler child process fails to spawn (e.g. intermittent spawn EBADF on macOS under fd pressure), the scss worker currently caches the dead compiler forever: initAsyncCompiler() resolves before the spawn settles, so the failure only surfaces per-compileStringAsync call, and compilerPromise ??= never re-runs. One lost race means every scss compile fails until the dev server is restarted.

This change retries once: if a compile rejects with a process-spawn error (err.syscall starting with spawn — real sass errors don't have it and are rethrown unchanged), the cached compiler is dropped and disposed fire-and-forget, and the compile runs again against a freshly spawned process.

Alternatives considered: retrying inside initAsyncCompiler isn't possible from Vite's side (it never rejects), and resetting only in stop() doesn't help a long-lived server. Scoping the retry to syscall: 'spawn*' errors keeps deliberate failures (bad scss, missing files) untouched.

Tests: not included — exercising this requires making sass-embedded's internal child_process.spawn fail once, and neither makeScssWorker nor a spawn seam is exported. I validated the equivalent retry logic against a stubbed compiler externally (single shared respawn under concurrent failures, sass errors pass through with zero retries), plus pnpm -F vite build, typecheck, and the css unit tests. Happy to add a test if you can suggest a seam you'd accept.

AI disclosure (per the AI policy): this fix was developed with AI assistance under my direction, including the root-cause investigation (module-resolution traces and reproduction of the EBADF cascade against a large app). I reviewed the final diff line by line; the retry scoping (syscall gate, single retry, fire-and-forget dispose of the dead compiler) reflects deliberate choices to keep the change minimal and never mask real compile errors.

Sign up for free to 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.

A single failed sass-embedded compiler spawn permanently breaks all scss compilation until server restart

1 participant