abhigyanpatwari/GitNexus · error
Worker ${workerIndex} parse job exhausted cumulative timeout
Error message
Worker ${workerIndex} parse job exhausted cumulative timeout budget. Surfacing in-flight file(s). What it means
Layer 5 of timeout handling: each job accumulates its timeout budget across retries (cumulativeTimeoutMs + next backoff). When the next cumulative value would exceed maxCumulativeTimeoutMs (option, or GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS, defaulting to a multiple of the sub-batch idle timeout), the pool stops retrying: it warns with the budget numbers and surfaced files, then returns give-up so the failure becomes a WorkerPoolDispatchError instead of an infinite exponential-backoff stall.
Source
Thrown at gitnexus/src/core/ingestion/workers/worker-pool.ts:1857
job: WorkerJob<TInput>,
lastProgress: number,
inFlightPath: string | undefined,
): TimeoutDecision => {
const nextTimeout = Math.ceil(job.timeoutMs * poolOptions.timeoutBackoffFactor);
const nextCumulative = job.cumulativeTimeoutMs + nextTimeout;
// Layer 5: respect the per-job cumulative timeout budget. Once
// exhausted, surface the in-flight file via WorkerPoolDispatchError
// instead of letting exponential backoff stall further.
if (nextCumulative > poolOptions.maxCumulativeTimeoutMs) {
const firstPath = itemPath(job.items[0]);
const exhausted: string[] =
inFlightPath !== undefined
? [inFlightPath]
: firstPath !== undefined
? [firstPath]
: [];
logger.warn(
{
workerIndex,
cumulativeMs: job.cumulativeTimeoutMs,
nextCumulativeMs: nextCumulative,
maxCumulativeMs: poolOptions.maxCumulativeTimeoutMs,
exhausted,
},
`Worker ${workerIndex} parse job exhausted cumulative timeout budget. Surfacing in-flight file(s).`,
);
return {
kind: 'give-up',
reason:
`Worker ${workerIndex} parse job exhausted cumulative timeout budget ` +
`(${(nextCumulative / 1000).toFixed(0)}s > ${(poolOptions.maxCumulativeTimeoutMs / 1000).toFixed(0)}s cap)`,
excludePaths: exhausted,
};
}
View on GitHub (pinned to 0d1aed942f)
Solutions
- Raise GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS (and/or GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS) so the job can converge on your hardware
- Take the surfaced in-flight file from the error/warn and split, shrink, or exclude it — a file that eats the whole budget will do so again
- If the error aborts a large analyze run, re-run with the file excluded, then index it separately with a dedicated generous budget
- Report systematic cases upstream with the budget trace (cumulativeMs → nextCumulativeMs → maxCumulativeMs) from the warn
Example fix
# before export GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS= # default budget exhausted → give-up error # after export GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=1800000 npx gitnexus analyze # job converges inside the budget
Defensive patterns
Strategy: validation
Validate before calling
// Catch the give-up error and surface its file list:
try {
await pool.dispatch(jobs);
} catch (err) {
if (err instanceof WorkerPoolDispatchError) {
const budgetFiles = err.message.match(/exhausted cumulative timeout budget[\s\S]*/);
await writeLines('.gitnexusignore', extractPaths(budgetFiles?.[0] ?? ''));
}
throw err;
} Try / catch
// Pattern: distinguish budget exhaustion (config) from poison files (input)
try {
await runPool();
} catch (e) {
if (e instanceof WorkerPoolDispatchError && /cumulative timeout/i.test(e.message)) {
// raise GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS or exclude surfaced files, then retry once
} else throw e;
} Prevention
- Scale GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS with your largest repo and slowest runner
- Pre-split or exclude files that eat the whole budget — the surfaced in-flight list is the worklist
- Keep the timeout family consistent: idle timeout, retries, backoff, and cumulative budget move together
When it happens
Trigger: A parse job whose timeouts keep escalating — split/retry loops that grow nextCumulative past the configured ceiling; the in-flight path (or items[0]'s path as fallback) is surfaced in the warn and error so the operator knows which file ate the budget.
Common situations: Gigantic or pathological files that always exceed even raised timeouts, chains of splits on CI machines so slow that backoff accumulates fast, or a maxCumulativeTimeoutMs override that is too tight for legitimately large repos.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Worker ${workerIndex} timed out; retiring without immediate
- Worker ${workerIndex} parse job idle timeout. Splitting into
- Worker ${workerIndex} parse job idle timeout (single item).
- Worker ${workerIndex} parse job idle timeout exhausted retri
- Circuit '${key}' is open; retry in ${Math.ceil(retryAfterMs
AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-08-20).
Data as JSON: /api/errors/c1c0914153269d85.
Report an issue: GitHub.