thedotmack/claude-mem · error · Error
Worker request timed out after ${WORKER_FETCH_TIMEOUT_MS}ms:
Error message
Worker request timed out after ${WORKER_FETCH_TIMEOUT_MS}ms: ${url} What it means
Thrown by fetchWithTimeout() when the AbortController fires after WORKER_FETCH_TIMEOUT_MS (30000ms) and the resulting AbortError is re-interpreted as a worker timeout. The export script wraps every worker HTTP call in this 30-second bound, so any single request exceeding it produces this error rather than hanging indefinitely. Non-abort fetch errors are re-thrown unchanged.
Source
Thrown at scripts/export-memories.ts:42
const port = Number.parseInt(normalized, 10);
if (!Number.isInteger(port) || port < 1 || port > 65535 || String(port) !== normalized) {
throw new Error(`Invalid CLAUDE_MEM_WORKER_PORT in settings.json: ${rawPort}`);
}
return port;
}
async function fetchWithTimeout(url: string, init?: RequestInit): Promise<Response> {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), WORKER_FETCH_TIMEOUT_MS);
try {
return await fetch(url, {
...init,
signal: controller.signal,
});
} catch (error) {
if (error instanceof Error && error.name === 'AbortError') {
throw new Error(`Worker request timed out after ${WORKER_FETCH_TIMEOUT_MS}ms: ${url}`);
}
throw error;
} finally {
clearTimeout(timeout);
}
}
export async function exportMemories(query: string, outputFile: string, project?: string) {
const settings = SettingsDefaultsManager.loadFromFile(join(resolveDataDir(), 'settings.json'));
const port = parseWorkerPort(settings.CLAUDE_MEM_WORKER_PORT);
const baseUrl = `http://localhost:${port}`;
console.log(`🔍 Searching for: "${query}"${project ? ` (project: ${project})` : ' (all projects)'}`);
const params = new URLSearchParams({
query,
format: 'json',
limit: '999999'View on GitHub (pinned to d768ba3643)
Solutions
- Narrow the export: pass a more specific query and/or --project to reduce the result set so /api/search returns within 30s.
- Check worker health (logs, CPU, DB connection pool) and restart it if wedged.
- Confirm the worker port is correct so the request isn't hitting a dead listener that never RSTs.
- If large exports are expected, raise WORKER_FETCH_TIMEOUT_MS in the script and rebuild, or paginate the export in smaller batches.
Example fix
// before — single huge export
exportMemories('""', 'all.json')
// after — scoped, returns fast
exportMemories('auth', 'auth.json', 'claude-mem') Defensive patterns
Strategy: retry
Validate before calling
import { createConnection } from 'net';
const sock = createConnection({ host: '127.0.0.1', port }, () => { sock.end(); });
sock.on('error', () => { /* worker not listening */ }); Try / catch
try {
return await fetchWithTimeout(url, init);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Worker request timed out')) {
// narrow the query and retry once, or surface a 'reduce scope' message
}
throw e;
} Prevention
- Scope exports with a specific query and --project to keep /api/search responses well under 30s.
- Monitor worker DB/Chroma latency so slow queries are caught before they hit the export timeout.
- If large exports are routine, raise WORKER_FETCH_TIMEOUT_MS or paginate in batches.
When it happens
Trigger: Any fetchWithTimeout() call (search, sdk-sessions/batch) where the worker does not respond within 30s. Concretely: exporting a huge result set against /api/search with limit=999999, the worker blocked on a slow Postgres/Chroma query, the worker process wedged, or localhost loopback stalled.
Common situations: Large memory database where the hybrid search query plan is slow. Worker contending with the daemon for DB connections. A degenerate query that matches nearly every observation. Resource-constrained machine where the worker is swapping.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Request timed out after ${timeoutMs}ms
- ${timeoutMessage} (timed out after ${timeoutMs}ms)
- Failed to search: ${searchResponse.status} ${searchResponse.
- Failed to fetch SDK sessions: ${sessionsResponse.status} ${s
- SSE stream returned HTTP ${response.status}
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/97f225be8be20630.
Report an issue: GitHub.