abhigyanpatwari/GitNexus · warning

Worker ${record.workerIndex} is still inside native code aft

Error message

Worker ${record.workerIndex} is still inside native code after the ${poolOptions.shutdownDrainMs}ms shutdown drain; leaving it un-terminated to avoid a native abort (#2432). It will be terminated at its next safe point.

What it means

During pool shutdown, a retired worker that has not reached a JS-visible safe point may be inside an N-API (native parser) call; terminating it then aborts the whole process (Napi::Error → std::terminate → SIGABRT, #2432). The pool waits up to shutdownDrainMs for the worker's safe point; if the drain expires it leaves the worker un-terminated (unref'd, terminate listener still armed) and warns which worker wedged and why.

Source

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

  };

  const terminateTrackedWorkers = async (
    liveWorkers: readonly (Worker | undefined)[],
  ): Promise<void> => {
    const retired = Array.from(retiredWorkers);
    await Promise.all([
      ...liveWorkers.map((worker) => worker?.terminate().catch(() => undefined)),
      ...retired.map(async (record) => {
        // #2432: a retired worker that has not reached a JS-visible safe
        // point may be inside an N-API call — terminating it aborts the
        // WHOLE process (`Napi::Error` → std::terminate → SIGABRT). Drain:
        // wait (bounded) for its safe point; on expiry leave it running —
        // it is unref'd and its at-safe-point terminate listener stays
        // armed — and log which file wedged it.
        if (!record.safeToTerminate) {
          const drained = await settledWithin(record.safePoint, poolOptions.shutdownDrainMs);
          if (!drained) {
            logger.warn(
              {
                workerIndex: record.workerIndex,
                reason: record.reason,
                drainMs: poolOptions.shutdownDrainMs,
              },
              `Worker ${record.workerIndex} is still inside native code after the ` +
                `${poolOptions.shutdownDrainMs}ms shutdown drain; leaving it un-terminated ` +
                `to avoid a native abort (#2432). It will be terminated at its next safe point.`,
            );
            return;
          }
        }
        await record.terminate();
      }),
    ]);
    // Undrained records stay tracked so a repeated shutdown call can retry
    // their (now possibly safe) terminate; record.terminate() removes each
    // drained record via its cleanup.

View on GitHub (pinned to 0d1aed942f)

Solutions

  1. Raise GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS so wedged workers can reach a safe point before the drain expires
  2. Identify the wedging input from the warn's reason/context and exclude or shrink that file so native parse finishes promptly
  3. Accept the behavior when benign: the worker is unref'd, so the process can still exit; it self-terminates at its next safe point
  4. If processes hang after this warn, check for native leaks and report the file upstream with the drain stats

Example fix

# before
export GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=   # default drain expires → warn
# after
export GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=30000   # native parse reaches safe point, clean exit
Defensive patterns

Strategy: fallback

Validate before calling

// Give wedged native parses room before shutdown:
if (!process.env.GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS) {
  process.env.GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS = '30000';
}

Prevention

When it happens

Trigger: Shutting down the pool while a worker is mid-parse inside native code that outlasts the drain window — a pathological file (deep parse, huge grammar tree) or a native slowdown; settledWithin(record.safePoint, shutdownDrainMs) returns false and the warn fires with workerIndex, reason, and drainMs.

Common situations: Indexing repos with parser-hostile files right before shutdown, tight GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS overrides, slow/loaded CI machines stretching native parse time, or native grammar builds running slower than prebuilt ones.

Related errors


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