thedotmack/claude-mem · error
Worker API error (${response.status}): ${errorText}
Error message
Worker API error (${response.status}): ${errorText} What it means
Thrown by callWorker() inside the MCP server whenever the local worker HTTP endpoint returns a non-2xx response. The message embeds the raw HTTP status code and the response body text so the underlying worker error (auth, validation, 500, etc.) is surfaced verbatim. It is a generic relay of any worker-side failure to the MCP tool caller.
Source
Thrown at src/servers/mcp-server.ts:98
if (opts.body) {
response = await workerHttpRequest(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(opts.body)
});
} else {
const searchParams = new URLSearchParams();
for (const [key, value] of Object.entries(opts.query ?? {})) {
if (value !== undefined && value !== null) {
searchParams.append(key, String(value));
}
}
response = await workerHttpRequest(`${endpoint}?${searchParams}`);
}
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Worker API error (${response.status}): ${errorText}`);
}
logger.debug('SYSTEM', '← Worker API success', undefined, { endpoint });
if (opts.text) {
return { content: [{ type: 'text' as const, text: await response.text() }] };
}
if (opts.body) {
return { content: [{ type: 'text' as const, text: JSON.stringify(await response.json(), null, 2) }] };
}
return await response.json() as { content: Array<{ type: 'text'; text: string }>; isError?: boolean };
} catch (error: unknown) {
logger.error('SYSTEM', '← Worker API error', { endpoint }, error instanceof Error ? error : new Error(String(error)));
return {
content: [{
type: 'text' as const,
text: `Error calling Worker API: ${error instanceof Error ? error.message : String(error)}`
}],View on GitHub (pinned to d768ba3643)
Solutions
- Read the embedded status code and errorText — that is the real error; fix the worker-side cause it names (e.g. unknown corpus, corrupt DB).
- Confirm the worker is healthy: call GET /api/health and GET /api/readiness via workerHttpRequest; if either is non-OK, run ensureWorkerConnection() / restart the worker before retrying.
- Verify WORKER_SCRIPT_PATH resolves to the current built bundle and the port from getWorkerPort() matches the running listener.
- Reproduce the exact endpoint+payload the tool sent and call the worker route directly to isolate MCP-layer vs worker-layer faults.
Example fix
// before — error swallowed, only the relayed text seen
callWorker('/api/corpus/unknown/prime', { body: {} });
// returns { content:[{text:'Error calling Worker API: Worker API error (404): corpus not found'}], isError:true }
// after — surface status explicitly so callers can branch
if (!response.ok) {
const errorText = await response.text();
const err = new Error(`Worker API error (${response.status}): ${errorText}`);
(err as any).status = response.status;
throw err;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before calling a worker-backed tool, confirm the worker is up.
const health = await workerHttpRequest('/api/health');
if (!health.ok) {
throw new Error(`Worker unhealthy (status ${health.status}); aborting tool call`);
} Try / catch
// callWorker already wraps in try/catch and returns {content, isError:true}.
// At the tool boundary, branch on isError:
const result = await callWorker('/api/search', { query: args });
if (result.isError) {
// result.content[0].text holds 'Error calling Worker API: Worker API error (NNN): ...'
const m = result.content[0].text.match(/error \((\d+)\)/);
const status = m ? Number(m[1]) : null;
if (status && status >= 500) { /* transient — retry */ }
if (status === 404) { /* not found — handle */ }
} Prevention
- Run ensureWorkerConnection() before invoking worker-backed tools so auto-start has a chance.
- Surface the embedded HTTP status so callers can distinguish transient (5xx/429) from permanent (4xx) failures.
- Health-check the worker (/api/health, /api/readiness) on startup and after long idle periods.
When it happens
Trigger: Any MCP tool that delegates to callWorker() (search, timeline, get_observations, the corpus tools, session_start_context) will trigger this when the worker responds with status >= 400. Concretely: POST /api/corpus/<name>/prime with an unknown corpus name (404), GET /api/search?... when the worker's SQLite/Chroma is corrupt (500), or any endpoint when the worker process is mid-restart and returns 503.
Common situations: Worker bundle is stale (rebuilt from old source after an upgrade), worker port mismatch between getWorkerPort() and the actual listener, malformed tool arguments that pass MCP schema validation but fail worker-level validation, or the worker's backing store (SQLite file locked, Chroma offline) is unhealthy.
Related errors
- Failed to get processing status: ${res.status}
- Failed to trigger processing: ${res.status}
- Failed to search: ${searchResponse.status} ${searchResponse.
- Failed to fetch SDK sessions: ${sessionsResponse.status} ${s
- chroma-mcp transport error during "${toolName}" (retry faile
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/98d88f35b6a50a06.
Report an issue: GitHub.