Skip to content

fix(hyperframes-media): surface a clear error when npx can't be resolved on Windows - #1961

Merged
miguel-heygen merged 1 commit into
mainfrom
fix/tts-npx-resolution-loud
Jul 6, 2026
Merged

fix(hyperframes-media): surface a clear error when npx can't be resolved on Windows#1961
miguel-heygen merged 1 commit into
mainfrom
fix/tts-npx-resolution-loud

Conversation

@miguel-heygen

Copy link
Copy Markdown
Collaborator

Root cause

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 audio engine 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.

Reported (recurring): "surface a clear error like 'npm_execpath not set, cannot resolve npx on Windows' instead of silent generic failure."

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}. 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 a shell:true npx.cmd fallback to avoid arg-escaping/quoting risk.)

Test plan

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. node --check + oxlint/oxfmt clean; full bun run build clean.


This batch also gave PR #1959 a 3rd independent confirmation; the Lambda __dirname deferred 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 opaque background-color is 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.

…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
miguel-heygen marked this pull request as ready for review July 6, 2026 01:28
@miguel-heygen
miguel-heygen merged commit dfa6fed into main Jul 6, 2026
39 checks passed
@miguel-heygen
miguel-heygen deleted the fix/tts-npx-resolution-loud branch July 6, 2026 01:29
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).
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.

1 participant