{"record":{"id":"2bf64cfb441eeda6","repo":"abhigyanpatwari/GitNexus","slug":"worker-script-not-found-workerpath","errorCode":null,"errorMessage":"Worker script not found: ${workerPath}","messagePattern":"Worker script not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/ingestion/workers/worker-pool.ts","lineNumber":992,"sourceCode":" * `GITNEXUS_WORKER_HEAP_MB` overrides the formula. Exported for unit tests.\n */\nexport function resolveWorkerHeapCapMb(poolSize: number): number {\n  return (\n    positiveInteger(process.env.GITNEXUS_WORKER_HEAP_MB) ??\n    Math.min(4096, Math.max(512, Math.floor(effectiveRamBytes() / (1024 * 1024) / 2 / poolSize)))\n  );\n}\n\nexport const createWorkerPool = (\n  workerUrl: URL,\n  poolSize?: number,\n  options?: WorkerPoolOptions,\n): WorkerPool => {\n  // Validate worker script exists before spawning to prevent uncaught\n  // MODULE_NOT_FOUND crashes in worker threads (e.g. when running from src/ via vitest)\n  const workerPath = fileURLToPath(workerUrl);\n  if (!fs.existsSync(workerPath)) {\n    throw new Error(`Worker script not found: ${workerPath}`);\n  }\n\n  const size = poolSize ?? resolveAutoPoolSize();\n  const poolOptions = resolveWorkerPoolOptions(options, size);\n  // Production factory spawns with `{ stderr: true }` so a worker's crash\n  // output is redirected to a `worker.stderr` stream we can tee + capture\n  // (see captureWorkerStderr) and attach to readiness-failure messages —\n  // instead of the generic \"did not report ready\" that hid the real cause\n  // in #1741. Test factories (workerFactory) are used verbatim.\n  // Bake the (immutable) ParsedFile store path into the factory closure so it\n  // reaches EVERY spawned worker — including respawns, which reuse this same\n  // factory — via `workerData`, read once at worker init. The `(url) => Worker`\n  // signature is unchanged so the zero-arg test factories keep working.\n  const parsedFileStoreStoragePath = options?.parsedFileStoreStoragePath;\n  const durableParsedFileStoragePath = options?.durableParsedFileStoragePath;\n  // CFG/PDG opt-in (#2081 M1) — carried in workerData alongside the store paths.\n  const pdg = options?.pdg === true;\n  const pdgMaxFunctionLines = options?.pdgMaxFunctionLines;","sourceCodeStart":974,"sourceCodeEnd":1010,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/ingestion/workers/worker-pool.ts#L974-L1010","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Build the project (`tsc` / `npm run build`) so the compiled worker script exists at the expected path.","Verify the `workerUrl` is constructed from the correct `import.meta.url` base and points to the shipped worker entry.","If running from source in a test, use the test `workerFactory` hook or ensure the dev build emits the worker script.","Check the printed resolved path actually exists with `ls <resolvedPath>`; fix packaging if it is absent from the dist tree."],"exampleFix":"// before — wrong/relative base resolves to a missing file\nconst pool = createWorkerPool(new URL('./worker.js', import.meta.url));\n// → Worker script not found: /app/lib/worker.js\n\n// after — point at the compiled worker entry\nconst pool = createWorkerPool(new URL('./workers/worker-entry.js', import.meta.url));","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\n\nconst workerUrl = new URL('./workers/worker-entry.js', import.meta.url);\nconst workerPath = fileURLToPath(workerUrl);\nif (!existsSync(workerPath)) {\n  throw new Error(`Worker script missing before pool creation: ${workerPath}. Build the project first.`);\n}\nconst pool = createWorkerPool(workerUrl);","typeGuard":null,"tryCatchPattern":"try {\n  const pool = createWorkerPool(workerUrl);\n} catch (err) {\n  if (/Worker script not found/.test(err.message)) {\n    // Build step omitted the worker entry — run the build, then retry.\n    console.error(err.message, '— run `npm run build` to emit the worker bundle.');\n    process.exit(4);\n  }\n  throw err;\n}","preventionTips":["Always run the build step before invoking createWorkerPool from compiled output.","In tests, use the provided workerFactory test hook rather than pointing at a non-existent script.","Construct workerUrl from import.meta.url so it resolves against the module's real location."],"tags":["worker-pool","startup","build","path","vitest"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}