Repository navigation
Description
Summary
The drawElement parallel-router experiment (HF_DE_PARALLEL_ROUTER) is enabled by default. On WSL2 it hangs native capture at frame 0/300 for ~60 s with zero console output — no error, no warning, no progress.
The per-install circuit breaker that should retire the experiment after a bad render never armed across 5 consecutive failed renders. Reading dist/cli.js from the published 0.8.10 bundle, that appears structural rather than incidental: the breaker latches only when the router "reverted", and a hang produces no outcome to latch on.
Environment
- hyperframes 0.8.10, installed globally via npm
- WSL2 / Ubuntu on Windows 11
- 300-frame mp4 composition using drawElement capture
- Code analysis below is against the same 0.8.10 npm bundle, read on macOS
Default-on is unconditional
// dist/cli.js:129066
function isDeParallelRouterEnabled(env) {
const raw = env.HF_DE_PARALLEL_ROUTER?.trim().toLowerCase();
if (raw === void 0 || raw === "") return true; // unset => ON
return !(raw === "false" || raw === "0" || raw === "off" || raw === "no");
}shouldPreferParallelDrawElement (dist/cli.js:129071) gates on worker count, output format, drawElement usage and a RAM floor. There is no install-age, render-count or trial-cohort term — every install with >1 worker doing an mp4 drawElement render is routed.
Why the safety net never armed
// dist/cli.js:145071
function maybeConsumeDeParallelRouterTrial(routerActive, job, quiet) {
if (!routerActive) return;
const outcome = resolveDeParallelRouterOutcome(job);
if (outcome === void 0) return; // <-- a hang exits here
...
const fired = outcome === "reverted"; // <-- only a graceful revert latches
if (fired) { config.deParallelRouterTrialFired = true; ... }
}resolveDeParallelRouterOutcome reads job.perfSummary?.drawElement?.parallelRouter ?? job.errorDetails?.observability?.capture.deParallelRouter. A render that stalls and is killed populates neither, so outcome is undefined and the function returns before writing the latch.
Both call sites — dist/cli.js:144855 in the catch, and :144868 after success — require executeRenderJob to return or throw. A stalled process the user interrupts reaches neither.
Net effect: the breaker covers the failure mode that already recovered on its own (verify-fail → revert → continue), and is inert against the one that does not (indefinite silent hang). The experiment stays armed for the next render, indefinitely.
There is a second path on which it cannot arm: when options.manageDeParallelRouterBreaker !== true, deParallelRouterActive is set to false, and the in-source comment at dist/cli.js:144809-144812 states the router still runs but the trip is "neither enforced nor recorded."
Reproduction
unset HF_DE_PARALLEL_ROUTER
cd <project> && hyperframes render > /tmp/stall.log 2>&1; echo $?Redirect rather than pipe — a pipe reports the tail's exit status, not the render's.
Observed: stalls at frame 0/300 for ~60 s, no console errors, 5/5 renders failed.
With HF_DE_PARALLEL_ROUTER=0: the same composition renders to completion — 306.6 KB, beginFrameStalled: false, verified by extracting and viewing frames rather than trusting the exit code.
Not a Chrome or WSL capability problem: raw chrome-headless-shell --screenshot works normally in the same environment (9,887 B, exit 0).
Config after 5 failed renders: ~/.hyperframes/config.json contained no deParallelRouterTrialFired key.
Suggested fixes
- Latch the breaker on any non-success of a routed render, not only on
"reverted". - Arm a pre-render latch that a successful render clears, so a killed process still leaves evidence behind.
- Emit something during the stall — 60 s of silence gives the user nothing to search for, which is what made this take five renders to localize.
Possibly related
#3423 reports a drawElement capture path failing at frame 0 where a documented fallback did not trigger. Different flag and a hard error rather than silence, so likely distinct, but the "documented fallback did not happen" shape is the same.
Activity
fix(producer): trip DE parallel-router circuit breaker on stalls and …