Skip to content

fix(compression): pass a URL object when spawning the LLMLingua worker - #13093

Merged
diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
huuhungn:fix/llmlingua-worker-spawn-12822
Sep 11, 2026
Merged

diegosouzapw merged 1 commit into
diegosouzapw:release/v3.8.51from
huuhungn:fix/llmlingua-worker-spawn-12822

Conversation

@anhtahaylove

Copy link
Copy Markdown
Contributor

ensureWorker() called new Worker(pathToFileURL(absoluteWorkerFile).href, { execArgv }), which passes a string. node:worker_threads treats a string argument as a filesystem path and requires it to start with ./ or ../; only a URL instance is interpreted as a file: URL. So the "file://..." text was looked up literally as a relative path and the spawn threw ERR_WORKER_PATH.

The failure was silent. pump() wraps ensureWorker() in a bare catch {} and fails open, so every compression call quietly degraded to a passthrough while still reporting success — the worst shape for this bug, since nothing in the logs or the response says compression did not happen.

Confirmed against a real Worker on Node 24, isolated from this codebase:

href string -> ERR_WORKER_PATH
URL object  -> OK

The change

One argument: drop .href and pass the URL object.

pathToFileURL stays — the sibling test llmlingua-worker-resolution.test.ts asserts this file never touches import.meta.url or createRequire (both die in the standalone webpack bundle), and pathToFileURL is a pure path→URL converter with neither dependency. Passing the raw path instead would also work on Node, but the URL form is what keeps spaces and non-ASCII in the install path unambiguous.

Test

tests/unit/compression/llmlingua-worker-spawn-12822.test.ts asserts the source does not spawn with .href, and separately proves the runtime contract by spawning both spellings against a real worker file — so it stays honest if the call is ever reshaped rather than just matching text.

Verification

llmlingua-worker-spawn-12822 + llmlingua-worker-resolution + llmlingua-failopen   21 passed
npx tsc -p tsconfig.typecheck-core.json --noEmit    clean
npx eslint <changed files>                           clean

Fixes #12822

ensureWorker() called `new Worker(pathToFileURL(file).href, ...)`, which passes
a STRING. node:worker_threads treats a string argument as a filesystem path and
requires it to start with ./ or ../, so a "file://..." string is looked up
literally and throws ERR_WORKER_PATH. Only a URL instance is interpreted as a
file: URL.

The failure was silent: pump() wraps ensureWorker() in `catch {}` and fails open,
so every compression call degraded to a passthrough while reporting success.

Verified against a real Worker on Node 24: the .href spelling throws
ERR_WORKER_PATH, the URL object spawns cleanly.

Fixes diegosouzapw#12822
@anhtahaylove

Copy link
Copy Markdown
Contributor Author

Note on the checks here: the workflows are sitting in action_required because this is my first PR to this repo, so GitHub holds them for maintainer approval. The three green checks shown (Mergify, semgrep) are the ones that run without it — the test and typecheck jobs have not run yet. Approving the workflow run will give you the real signal.

Locally on Windows 11 / Node 24.19.0: tsc -p tsconfig.typecheck-core.json --noEmit and eslint are clean on the changed files, and the touched suites pass. The 5 failures in the full tests/unit/compression/** run are pre-existing RTK cases that reproduce on a clean release/v3.8.51 checkout with my changes stashed.

@diegosouzapw
diegosouzapw merged commit 66330cc into diegosouzapw:release/v3.8.51 Sep 11, 2026
3 checks passed
diegosouzapw added a commit to insoln/OmniRoute that referenced this pull request Sep 16, 2026
Reconcile with diegosouzapw#13093 (LLMLingua URL-object spawn fix) and diegosouzapw#13091
(idle-worker terminate() / remove(slot) signature): keep this PR's
llmlinguaWorkerSpecifier()+workerFactory seam (superset of diegosouzapw#13093's
inline fix — also testable and wired to notifyCompressionFailOpen),
and drop the removed terminate boolean from every remove(slot) call
site, including the close() drain path this PR adds.

Update diegosouzapw#13093's own source-pattern regression test
(llmlingua-worker-spawn-12822.test.ts) to match the new call shape —
it still asserts the same contract (a URL instance, never .href, is
passed to the worker), just via llmlinguaWorkerSpecifier() instead of
inlined pathToFileURL().

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
diegosouzapw#13093)

`node:worker_threads` only treats a `URL` instance as a `file:` URL — a string must be a relative path. The silent `catch {}` in `pump()` made this degrade compression to a passthrough while still reporting success, which is the worst shape for it.

---

Validated in one consolidated worktree cut from `release/v3.8.51`, boarded together with the other 13 PRs of this batch — zero merge conflicts between them.

- `typecheck:core` clean
- complexity 2799 / baseline 3218 and cognitive-complexity 1265 / baseline 1437 — both under baseline
- 71 focused assertions green across the 13 test files this batch adds or touches

⚠️ base-red inherited: diegosouzapw#12732 — `Docs Gates (fast-path)`, `Merge integrity`, `No new ESLint warnings`, `Unit Tests fast-path` and `Fast Quality Gates` all reproduce on the pure `release/v3.8.51` tip (provider count 356 vs the 358 the modules define, SKILL.md drift, and `open-sse/utils/stream.ts` at 3115 > frozen 3098). None of them touch this diff.

Thanks @anhtahaylove — the root-cause write-up, the measured before/after numbers and the red-before-green proof on every one of these made the batch reviewable as a unit.
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.

fix(backend): LLMLingua worker never spawns: new Worker() gets a file:// string, throws ERR_WORKER_PATH, silently fail-opens

2 participants