abhigyanpatwari/GitNexus · warning

Worker ${workerIndex} parse job idle timeout (single item).

Error message

Worker ${workerIndex} parse job idle timeout (single item). Retrying with ${nextTimeout / 1000}s timeout.

What it means

When a single-item job times out (nothing left to split) and retries remain (nextAttempt <= maxTimeoutRetries), the job is requeued with attempt+1 and a grown timeout (backoff factor applied). The warn shows the current timeout, the attempt as attempt/maxAttempts, and the next timeout in seconds — the last tolerated retry before quarantine.

Source

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

              workerIndex,
              timeoutSec: job.timeoutMs / 1000,
              items: job.items.length,
              estimatedBytes: job.estimatedBytes,
              lastProgress,
              firstSplitItems: first.items.length,
              secondSplitItems: second.items.length,
              nextTimeoutSec: nextTimeout / 1000,
            },
            `Worker ${workerIndex} parse job idle timeout. Splitting into ${first.items.length}/${second.items.length} item jobs.`,
          );
          // Preserve intuitive retry order; final result order is still enforced by startIndex sort.
          jobs.unshift(first, second);
          return { kind: 'retry' };
        }

        const nextAttempt = job.attempt + 1;
        if (nextAttempt <= poolOptions.maxTimeoutRetries) {
          logger.warn(
            {
              workerIndex,
              timeoutSec: job.timeoutMs / 1000,
              attempt: nextAttempt,
              maxAttempts: poolOptions.maxTimeoutRetries + 1,
              nextTimeoutSec: nextTimeout / 1000,
            },
            `Worker ${workerIndex} parse job idle timeout (single item). Retrying with ${nextTimeout / 1000}s timeout.`,
          );
          jobs.unshift({
            ...job,
            attempt: nextAttempt,
            timeoutMs: nextTimeout,
            cumulativeTimeoutMs: nextCumulative,
          });
          return { kind: 'retry' };
        }

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Usually no action — the retry with a larger timeout resolves one-off slowness; verify the next attempt succeeds in the logs
  2. If the same file retraces this path every run, raise GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS so the first attempt suffices
  3. Watch the attempt counter: hitting maxAttempts hands over to the quarantine path, so pre-emptively exclude a known-pathological file
  4. For systematically slow machines, scale the whole timeout family (sub-batch idle + cumulative budget) together

Example fix

# before
export GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=30000   # single item misses → repeated retry warns
# after
export GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=120000  # first attempt succeeds, no retry
Defensive patterns

Strategy: retry

Validate before calling

// Detect a file stuck on the retry ladder before it quarantines:
const retryWarns = [...logText.matchAll(/idle timeout \(single item\)\. Retrying with (\d+(?:\.\d+)?)s/g)];
if (retryWarns.filter((m) => Number(m[1]) >= 60).length > 0) {
  flagSlowParsers(extractRecentFiles(logText));
}

Prevention

When it happens

Trigger: An idle timeout on a one-item job whose attempt counter is still under the retry budget: jobs.unshift({...job, attempt: nextAttempt, timeoutMs: nextTimeout, cumulativeTimeoutMs: nextCumulative}) requeues it with the escalated budget.

Common situations: A single slow-to-parse file (huge generated source, pathological nesting) that needs one or two bigger timeouts to finish; overloaded CI runners making first attempts miss; backoff factors too small for very large files.

Understand the failure class

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-08-20). Data as JSON: /api/errors/22f22039255ab2d2. Report an issue: GitHub.