abhigyanpatwari/GitNexus · error · WorkerPoolDispatchError

Worker pool circuit breaker tripped${reason}. Subsequent dis

Error message

Worker pool circuit breaker tripped${reason}. Subsequent dispatches require a fresh pool instance.

What it means

Thrown by `dispatch()` when the pool's circuit breaker has already tripped (`poolBroken === true`). The circuit breaker is set when the pool suffers a catastrophic, non-recoverable failure; once set, every subsequent dispatch to the SAME pool instance re-throws this `WorkerPoolDispatchError`. The pool is dead — the message explicitly states that subsequent dispatches require a fresh pool instance. The error carries the triggering `poolFailure.message` as the reason.

Source

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

  ).then(() => undefined);

  const dispatch = async <TInput, TResult>(
    items: TInput[],
    onProgress?: (filesProcessed: number) => void,
    chunkHash?: string,
  ): Promise<TResult[]> => {
    // Await the initial-spawn readiness gate (F13). On first dispatch
    // this blocks for up to poolOptions.workerReadyTimeoutMs while every initial
    // worker's `{type:'ready'}` handshake is checked; on subsequent
    // dispatches the promise is already settled and resolves
    // synchronously. Slots whose initial worker crashed in top-of-
    // script init have been dropped from `activeSlots` by the gate
    // before this point — they don't surface here as "no active
    // workers" until *all* initial slots fail.
    await initialReadyGate;
    if (poolBroken) {
      const reason = poolFailure ? `: ${poolFailure.message}` : '';
      throw new WorkerPoolDispatchError(
        `Worker pool circuit breaker tripped${reason}. ` +
          `Subsequent dispatches require a fresh pool instance.`,
        [],
      );
    }
    if (items.length === 0) return [];
    if (activeSlots.size === 0) {
      const detail =
        initialReadinessFailures.length > 0
          ? ` after initial ready handshake: ${initialReadinessFailures.join('; ')}`
          : '';
      // The bounded self-heal exhausted (or short-circuited a deterministic
      // crash-loop). Classify automatically so the caller renders the real
      // cause without consulting any operator flag (#1741).
      const crashClass: StartupCrashClass = deterministicStartupDetected
        ? 'deterministic-startup'
        : 'transient-exhausted';
      throw new WorkerPoolInitializationError(

View on GitHub (pinned to d540b00184)

Solutions

  1. Create a FRESH pool instance (`createWorkerPool(...)`) before dispatching again — a broken pool cannot be reset.
  2. Inspect the `reason` (the original `poolFailure.message`) to fix the underlying cause before recreating the pool.
  3. After a dispatch throws, always discard the pool reference and rebuild it for the next batch rather than retrying on the same instance.

Example fix

// before — reuse a pool after it broke
const pool = createWorkerPool(url);
try { await pool.dispatch(batchA); } catch { /* swallowed */ }
await pool.dispatch(batchB); // → Worker pool circuit breaker tripped...

// after — recreate the pool after a failure
let pool = createWorkerPool(url);
try {
  await pool.dispatch(batchA);
} catch {
  pool = createWorkerPool(url); // fresh instance
}
await pool.dispatch(batchB);
Defensive patterns

Strategy: fallback

Type guard

import { WorkerPoolDispatchError } from 'gitnexus/dist/core/ingestion/workers/worker-pool.js';

function isPoolBroken(err): err is WorkerPoolDispatchError {
  return err instanceof WorkerPoolDispatchError
    || /circuit breaker tripped/i.test(err.message);
}

Try / catch

// Recreate the pool after a circuit-breaker trip — a broken pool is not reusable.
let pool = createWorkerPool(url);
for (const batch of batches) {
  try {
    await pool.dispatch(batch);
  } catch (err) {
    if (/circuit breaker tripped/i.test(err.message)) {
      pool = createWorkerPool(url); // fresh instance, fix root cause first
      continue;
    }
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling `pool.dispatch(...)` a second (or later) time after the pool already broke during a prior dispatch — e.g. an unrecoverable worker-death cascade tripped the breaker, and the caller did not recreate the pool before the next chunk dispatch.

Common situations: A parse loop that reuses one pool across many chunks and continues dispatching after an earlier chunk's fatal pool failure; a caller that swallowed a prior dispatch error without checking whether the pool was still usable.

Related errors


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