abhigyanpatwari/GitNexus · error · Error

Worker script not found: ${workerPath}

Error message

Worker script not found: ${workerPath}

What it means

A startup precondition check in `createWorkerPool`: before spawning any worker thread, it converts the `workerUrl` to a filesystem path and confirms the script file exists. This prevents an uncaught `MODULE_NOT_FOUND` crash inside a worker thread (which surfaces as a generic, hard-to-diagnose 'did not report ready' failure). If the script is missing, the pool fails fast with the resolved path so the operator can fix the build or path.

Source

Thrown at gitnexus/src/core/ingestion/workers/worker-pool.ts:992

 * `GITNEXUS_WORKER_HEAP_MB` overrides the formula. Exported for unit tests.
 */
export function resolveWorkerHeapCapMb(poolSize: number): number {
  return (
    positiveInteger(process.env.GITNEXUS_WORKER_HEAP_MB) ??
    Math.min(4096, Math.max(512, Math.floor(effectiveRamBytes() / (1024 * 1024) / 2 / poolSize)))
  );
}

export const createWorkerPool = (
  workerUrl: URL,
  poolSize?: number,
  options?: WorkerPoolOptions,
): WorkerPool => {
  // Validate worker script exists before spawning to prevent uncaught
  // MODULE_NOT_FOUND crashes in worker threads (e.g. when running from src/ via vitest)
  const workerPath = fileURLToPath(workerUrl);
  if (!fs.existsSync(workerPath)) {
    throw new Error(`Worker script not found: ${workerPath}`);
  }

  const size = poolSize ?? resolveAutoPoolSize();
  const poolOptions = resolveWorkerPoolOptions(options, size);
  // Production factory spawns with `{ stderr: true }` so a worker's crash
  // output is redirected to a `worker.stderr` stream we can tee + capture
  // (see captureWorkerStderr) and attach to readiness-failure messages —
  // instead of the generic "did not report ready" that hid the real cause
  // in #1741. Test factories (workerFactory) are used verbatim.
  // Bake the (immutable) ParsedFile store path into the factory closure so it
  // reaches EVERY spawned worker — including respawns, which reuse this same
  // factory — via `workerData`, read once at worker init. The `(url) => Worker`
  // signature is unchanged so the zero-arg test factories keep working.
  const parsedFileStoreStoragePath = options?.parsedFileStoreStoragePath;
  const durableParsedFileStoragePath = options?.durableParsedFileStoragePath;
  // CFG/PDG opt-in (#2081 M1) — carried in workerData alongside the store paths.
  const pdg = options?.pdg === true;
  const pdgMaxFunctionLines = options?.pdgMaxFunctionLines;

View on GitHub (pinned to d540b00184)

Solutions

  1. Build the project (`tsc` / `npm run build`) so the compiled worker script exists at the expected path.
  2. Verify the `workerUrl` is constructed from the correct `import.meta.url` base and points to the shipped worker entry.
  3. If running from source in a test, use the test `workerFactory` hook or ensure the dev build emits the worker script.
  4. Check the printed resolved path actually exists with `ls <resolvedPath>`; fix packaging if it is absent from the dist tree.

Example fix

// before — wrong/relative base resolves to a missing file
const pool = createWorkerPool(new URL('./worker.js', import.meta.url));
// → Worker script not found: /app/lib/worker.js

// after — point at the compiled worker entry
const pool = createWorkerPool(new URL('./workers/worker-entry.js', import.meta.url));
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';

const workerUrl = new URL('./workers/worker-entry.js', import.meta.url);
const workerPath = fileURLToPath(workerUrl);
if (!existsSync(workerPath)) {
  throw new Error(`Worker script missing before pool creation: ${workerPath}. Build the project first.`);
}
const pool = createWorkerPool(workerUrl);

Try / catch

try {
  const pool = createWorkerPool(workerUrl);
} catch (err) {
  if (/Worker script not found/.test(err.message)) {
    // Build step omitted the worker entry — run the build, then retry.
    console.error(err.message, '— run `npm run build` to emit the worker bundle.');
    process.exit(4);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling `createWorkerPool(workerUrl, ...)` where `workerUrl` resolves to a file that does not exist on disk. Common when running uncompiled `src/` under vitest (the compiled worker bundle isn't present), when a packaging step omitted the worker entry, or when a relative URL resolves against the wrong base.

Common situations: Running tests from source via vitest where the worker bundle has not been built; a custom build that did not emit the worker entry script; passing an incorrect `import.meta.url`-relative path; a stale build after the worker file was renamed.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/2bf64cfb441eeda6. Report an issue: GitHub.