abhigyanpatwari/GitNexus · error · WorkerPoolDisabledError
Worker-pool parsing cannot be disabled (${reason}). GitNexus
Error message
Worker-pool parsing cannot be disabled (${reason}). GitNexus no longer has a sequential parser — the worker pool self-heals via quarantine + respawn, so there is no slower path to fall back to. Pass `--workers <N>` with N>=1, or omit it for an auto-sized pool. What it means
Thrown by the parse phase when the worker pool is explicitly disabled. GitNexus removed its sequential (in-process) parser, so the worker pool — with quarantine, respawn, and a circuit breaker — is the ONLY parse path. There is no slower fallback to silently degrade to, so the three legacy disable channels (`skipWorkers: true`, `--workers 0`/`workerPoolSize=0`, and `GITNEXUS_WORKER_POOL_SIZE=0`) are now hard configuration errors instead of feature switches. The check only fires when there are parseable files; a repo with zero parseable files is exempt.
Source
Thrown at gitnexus/src/core/ingestion/pipeline-phases/parse-impl.ts:553
});
}
// Sequential parsing has been removed: the worker pool (quarantine +
// respawn/recycle + circuit breaker) is the sole parse path. The three
// channels that used to select an in-process parser are now hard errors, so
// an operator who set one gets an actionable message instead of a silently
// slower (now nonexistent) fallback. Validated before any chunk work; a
// zero-parseable-file repo is exempt (nothing to parse).
if (totalParseable > 0) {
const requestedPoolSize = options?.workerPoolSize;
const disabledByEnv = requestedPoolSize === undefined && workerPoolDisabledByEnv();
if (options?.skipWorkers || requestedPoolSize === 0 || disabledByEnv) {
const reason = options?.skipWorkers
? '`skipWorkers: true` was passed'
: requestedPoolSize === 0
? '`--workers 0` (workerPoolSize=0) was requested'
: '`GITNEXUS_WORKER_POOL_SIZE=0` is set';
throw new WorkerPoolDisabledError(
`Worker-pool parsing cannot be disabled (${reason}). GitNexus no longer ` +
`has a sequential parser — the worker pool self-heals via quarantine + ` +
`respawn, so there is no slower path to fall back to. Pass ` +
`\`--workers <N>\` with N>=1, or omit it for an auto-sized pool.`,
);
}
}
// Build byte-budget chunks. The budget is resolved per-call (U14): options
// first, then env, then the built-in default. Pre-U14 this was a
// module-load IIFE constant, which froze the env value at import time
// and made `PipelineOptions.chunkByteBudget` silently no-op on warm test
// runs. Resolving in the function body restores per-call configurability
// and matches the pattern used by resolveAutoPoolSize and the U1
// parseChunkConcurrency resolver.
// Effective worker count, computed up-front so the chunk budget can scale to
// keep the whole pool busy (#worker-idle). The pool is ALWAYS used (sequential
// parsing was removed; the disabled channels threw above). Size it to theView on GitHub (pinned to d540b00184)
Solutions
- Pass `--workers <N>` with N>=1, or omit `--workers` entirely so the pool auto-sizes to `os.availableParallelism() - 1` (clamped to the cap).
- Unset `GITNEXUS_WORKER_POOL_SIZE` from the environment (check `.env`, CI config, shell profiles) if you did not set it explicitly.
- Remove `skipWorkers: true` from the `PipelineOptions` object you pass to the analyze API.
- If you genuinely need single-worker parsing for debugging, pass `--workers 1` rather than disabling the pool.
Example fix
// before
const options = { skipWorkers: true };
await analyze(repo, options); // throws WorkerPoolDisabledError
// after — let the pool auto-size
const options = {};
await analyze(repo, options);
// or pin to a single worker for debugging
const options = { workerPoolSize: 1 }; Defensive patterns
Strategy: validation
Validate before calling
// Before calling analyze, validate the worker-pool config
import { workerPoolDisabledByEnv } from 'gitnexus/dist/core/ingestion/workers/worker-pool.js';
function assertWorkerPoolUsable(options) {
if (options?.skipWorkers) {
throw new Error('Refusing to analyze: skipWorkers is set but the worker pool is the only parser.');
}
if (options?.workerPoolSize === 0) {
throw new Error('Refusing to analyze: workerPoolSize=0 is not allowed.');
}
if (options?.workerPoolSize === undefined && workerPoolDisabledByEnv()) {
throw new Error('Refusing to analyze: GITNEXUS_WORKER_POOL_SIZE=0 is set in the environment.');
}
}
assertWorkerPoolUsable(options);
await analyze(repo, options); Type guard
// Narrow PipelineOptions to ensure the pool is not disabled
type WorkerPoolSafeOptions = {
skipWorkers?: false;
workerPoolSize?: number; // must be >= 1
};
function isWorkerPoolSafe(o): o is WorkerPoolSafeOptions {
return o.skipWorkers !== true && o.workerPoolSize !== 0;
} Try / catch
try {
await analyze(repo, options);
} catch (err) {
if (err.name === 'WorkerPoolDisabledError') {
// config error — fix the flag/env and re-run, do not retry as-is
console.error(err.message);
process.exit(2);
}
throw err;
} Prevention
- Never set GITNEXUS_WORKER_POOL_SIZE=0 in CI/shell profiles — it is a legacy switch that no longer works.
- Audit PipelineOptions before calling analyze; treat skipWorkers/workerPoolSize=0 as programmer errors.
- When upgrading GitNexus, grep your environment and scripts for removed worker-pool disable flags.
When it happens
Trigger: Calling `analyze`/`processParsing` with `PipelineOptions.skipWorkers = true`; passing `--workers 0` on the CLI (workerPoolSize=0); or having `GITNEXUS_WORKER_POOL_SIZE=0` set in the environment while no explicit positive `workerPoolSize` is passed — all only when `totalParseable > 0`.
Common situations: An operator who read old docs sets `GITNEXUS_WORKER_POOL_SIZE=0` to debug single-threaded parsing (that path no longer exists). A CI script pins `--workers 0` to reduce memory. A test harness passes `skipWorkers: true` expecting the legacy in-process fallback. An upgrade from an older GitNexus version leaves the now-invalid env var exported in a shell profile.
Related errors
- Analyze stopped before running out of memory: ${heapUsedMB}M
- GITNEXUS_EMBEDDING_DIMS must be a positive integer, got "${p
- ${TRUSTED_CACHE_DIRECTORY_ENV} must name an absolute protect
- ${TRUSTED_CACHE_DIRECTORY_ENV} must name a pre-existing prot
- ${TRUSTED_CACHE_DIRECTORY_ENV} must not traverse symbolic li
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/2be48aba0a56d81f.
Report an issue: GitHub.