fix(hyperframes-media): surface a clear error when npx can't be resolved on Windows - #1961
Merged
Merged
Conversation
…ved on Windows
On Windows, resolveSpawnCommand routes `npx` through node + npm's
npx-cli.js (avoiding the un-spawnable npx.cmd), locating that CLI via
npm_execpath. When the script is run directly with `node audio.mjs`
instead of through npm/npx, npm_execpath is unset, so resolution returns
null and spawnP short-circuited to `{status:-1}` — silently. With
stdio:"ignore" hiding everything, callers just reported "TTS failed -
omitted" for every single line, giving no hint that the real cause was
an unresolvable npx. Debugging required reading the source.
Fix: when spawnP hits that null-resolution path, emit a clear one-time
diagnostic naming npm_execpath and the remedy (run via npx/npm, or export
npm_execpath) before returning {status:-1}. One-shot latch so a batch of
lines logs it once, not per line. Behavior is otherwise unchanged — still
returns {status:-1} and spawns nothing.
Test: new tts.spawn.test.mjs case — two consecutive win32 npx calls with
npm_execpath unset both return {status:-1}, nothing is spawned, and the
diagnostic (mentioning npm_execpath) is emitted exactly once. Existing
spawn tests unchanged (7/7 pass).
miguel-heygen
marked this pull request as ready for review
July 6, 2026 01:28
dahans-msft2
pushed a commit
to dahans-msft2/hyperframes
that referenced
this pull request
Aug 6, 2026
…ved on Windows (heygen-com#1961) On Windows, resolveSpawnCommand routes `npx` through node + npm's npx-cli.js (avoiding the un-spawnable npx.cmd), locating that CLI via npm_execpath. When the script is run directly with `node audio.mjs` instead of through npm/npx, npm_execpath is unset, so resolution returns null and spawnP short-circuited to `{status:-1}` — silently. With stdio:"ignore" hiding everything, callers just reported "TTS failed - omitted" for every single line, giving no hint that the real cause was an unresolvable npx. Debugging required reading the source. Fix: when spawnP hits that null-resolution path, emit a clear one-time diagnostic naming npm_execpath and the remedy (run via npx/npm, or export npm_execpath) before returning {status:-1}. One-shot latch so a batch of lines logs it once, not per line. Behavior is otherwise unchanged — still returns {status:-1} and spawns nothing. Test: new tts.spawn.test.mjs case — two consecutive win32 npx calls with npm_execpath unset both return {status:-1}, nothing is spawned, and the diagnostic (mentioning npm_execpath) is emitted exactly once. Existing spawn tests unchanged (7/7 pass).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
On Windows,
resolveSpawnCommandroutesnpxthrough node + npm'snpx-cli.js(avoiding the un-spawnablenpx.cmd), locating that CLI vianpm_execpath. When the audio engine is run directly withnode audio.mjsinstead of through npm/npx,npm_execpathis unset, so resolution returnsnullandspawnPshort-circuited to{status:-1}— silently. Withstdio:"ignore"hiding everything, callers just reported "TTS failed - omitted" for every single line, giving no hint that the real cause was an unresolvablenpx. Debugging required reading the source.Reported (recurring): "surface a clear error like 'npm_execpath not set, cannot resolve npx on Windows' instead of silent generic failure."
Fix
When
spawnPhits that null-resolution path, emit a clear one-time diagnostic namingnpm_execpathand the remedy (run vianpx/npm, or exportnpm_execpath) before returning{status:-1}. A one-shot latch keeps a batch of lines from repeating it per line. Behavior is otherwise unchanged — still returns{status:-1}and spawns nothing. (Chose the "loud error" option over ashell:truenpx.cmdfallback to avoid arg-escaping/quoting risk.)Test plan
New
tts.spawn.test.mjscase: two consecutive win32npxcalls withnpm_execpathunset both return{status:-1}, nothing is spawned, and the diagnostic (mentioningnpm_execpath) is emitted exactly once. Existing spawn tests unchanged — 7/7 pass.node --check+oxlint/oxfmtclean; fullbun run buildclean.This batch also gave PR #1959 a 3rd independent confirmation; the Lambda
__dirnamedeferred item turned out already-fixed upstream; and a recurring WCAG-contrast false positive (audit samples the pixel ring outside the element's bbox, so an element with its own opaquebackground-coloris measured against the surrounding background) is logged for follow-up — deferred as a browser-side heuristic I can't verify without a working headless-capture repro.