thedotmack/claude-mem · error · Error

${timeoutMessage} (timed out after ${timeoutMs}ms)

Error message

${timeoutMessage} (timed out after ${timeoutMs}ms)

What it means

fetchWithTimeout aborts the underlying fetch after WORKER_FETCH_TIMEOUT_MS (10s, scripts/check-pending-queue.ts:31) via an AbortController. When the abort fires, fetch rejects with an AbortError, which this helper rewraps into '<timeoutMessage> (timed out after <N>ms)'. The timeoutMessage is supplied per call site (health check, processing-status, processing POST).

Source

Thrown at scripts/check-pending-queue.ts:57

  status: string;
  isProcessing: boolean;
  queueDepth: number;
  activeSessions: number;
}

async function fetchWithTimeout(
  url: string,
  init: RequestInit | undefined,
  timeoutMessage: string,
  timeoutMs: number = WORKER_FETCH_TIMEOUT_MS,
): Promise<Response> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(url, { ...init, signal: controller.signal });
  } catch (err) {
    if ((err as { name?: string })?.name === 'AbortError') {
      throw new Error(`${timeoutMessage} (timed out after ${timeoutMs}ms)`);
    }
    throw err;
  } finally {
    clearTimeout(timer);
  }
}

async function checkWorkerHealth(): Promise<boolean> {
  try {
    const res = await fetchWithTimeout(
      `${WORKER_URL}/api/health`,
      undefined,
      'Health check did not respond',
    );
    return res.ok;
  } catch {
    return false;
  }

View on GitHub (pinned to d768ba3643)

Solutions

  1. Confirm the worker is responsive: curl -m 2 http://$CLAUDE_MEM_WORKER_HOST:$CLAUDE_MEM_WORKER_PORT/api/health — if it also hangs, the worker is blocked, not the script.
  2. Check worker logs for long-running tasks (Chroma sync, large observation batches) starving the HTTP loop; if so, reduce batch size or move embedding off the request thread.
  3. Verify CLAUDE_MEM_WORKER_HOST/PORT resolve to the right host (a blackholing IP will hit the 10s timeout rather than refuse).
  4. If legitimately slow endpoints are expected, raise WORKER_FETCH_TIMEOUT_MS in the script (conscious tradeoff — the default 10s is deliberate for interactive use).

Example fix

// before — default 10s timeout fires on a slow worker
const res = await fetchWithTimeout(`${WORKER_URL}/api/processing-status`, undefined, 'Failed to get processing status');

// after — allow a longer budget for known-slow endpoints
const res = await fetchWithTimeout(
  `${WORKER_URL}/api/processing-status`,
  undefined,
  'Failed to get processing status',
  30_000, // explicit timeout for the slow endpoint
);
Defensive patterns

Strategy: retry

Validate before calling

// Cheap liveness check before the real call to fail fast on a blackholing host:
async function workerQuick(host: string, port: string, ms = 2000): Promise<boolean> {
  const ctrl = new AbortController();
  const t = setTimeout(() => ctrl.abort(), ms);
  try { return (await fetch(`http://${host}:${port}/api/health`, { signal: ctrl.signal })).ok; }
  catch { return false; } finally { clearTimeout(t); }
}

Type guard

function isAbortError(e: unknown): boolean {
  return e instanceof Error && (e as { name?: string }).name === 'AbortError';
}

Try / catch

// fetchWithTimeout already centralises this (scripts/check-pending-queue.ts:45-63):
// catch AbortError -> rethrow as a typed timeout; rethrow everything else.
// Callers should wrap in try/catch and decide whether to retry or report.

Prevention

When it happens

Trigger: Any of the three worker endpoints (/api/health, /api/processing-status, /api/processing) taking longer than 10s to respond. Worker hung under heavy DB load, Chroma sync stalled, or network latency/blackhole to CLAUDE_MEM_WORKER_HOST:CLAUDE_MEM_WORKER_PORT.

Common situations: Worker processing a large backlog and not answering health/status promptly. Wrong WORKER_HOST/PORT env pointing at an address that blackholes (no RST, so the connect hangs to the timeout). Chroma embedding a huge batch and blocking the event loop.

Understand the failure class

Related errors


AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12). Data as JSON: /api/errors/33a5db9235fd12aa. Report an issue: GitHub.