thedotmack/claude-mem · warning
[claude-mem] Worker POST ${path} failed: ${message}
Error message
[claude-mem] Worker POST ${path} failed: ${message} What it means
The OpenCode plugin posts tool observations and session mappings fire-and-forget to the local claude-mem worker at http://CLAUDE_MEM_WORKER_HOST:CLAUDE_MEM_WORKER_PORT. This warning fires when the POST promise rejects with anything except ECONNREFUSED (which is suppressed because a not-yet-started worker is the normal case). Typical causes: connection reset mid-request, timeout, DNS failure on a custom host, or a non-worker process owning the port.
Source
Thrown at src/integrations/opencode-plugin/index.ts:119
}
const WORKER_BASE_URL = `http://${resolveWorkerHost()}:${resolveWorkerPort()}`;
const MAX_TOOL_RESPONSE_LENGTH = 1000;
const JSON_HEADERS: Record<string, string> = { "Content-Type": "application/json" };
function workerPostFireAndForget(
path: string,
body: Record<string, unknown>,
): void {
fetch(`${WORKER_BASE_URL}${path}`, {
method: "POST",
headers: JSON_HEADERS,
body: JSON.stringify(body),
}).catch((error: unknown) => {
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("ECONNREFUSED")) {
console.warn(`[claude-mem] Worker POST ${path} failed: ${message}`);
}
});
}
async function workerGetText(path: string): Promise<string | null> {
try {
const response = await fetch(`${WORKER_BASE_URL}${path}`, { headers: JSON_HEADERS });
if (!response.ok) {
console.warn(`[claude-mem] Worker GET ${path} returned ${response.status}`);
return null;
}
return await response.text();
} catch (error: unknown) {
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("ECONNREFUSED")) {
console.warn(`[claude-mem] Worker GET ${path} failed: ${message}`);
}
return null;View on GitHub (pinned to e2d1df569a)
Solutions
- Restart the worker (`npx claude-mem worker` or reinstall via `npx claude-mem install` so the service/daemon is re-registered).
- Verify reachability with the same URL the plugin uses: `curl -i http://127.0.0.1:$CLAUDE_MEM_WORKER_PORT/` and check the worker answers.
- Confirm CLAUDE_MEM_WORKER_PORT / CLAUDE_MEM_WORKER_HOST in ~/.claude-mem/settings.json match the running worker, then restart OpenCode so the plugin re-resolves WORKER_BASE_URL.
- If a custom host is set, check DNS/firewall for that host or revert CLAUDE_MEM_WORKER_HOST to 127.0.0.1.
Defensive patterns
Strategy: fallback
Validate before calling
// Health-check the worker before a session that depends on it:
async function workerUp(base: string): Promise<boolean> {
try {
const r = await fetch(`${base}/`, { signal: AbortSignal.timeout(1000) });
return r.ok || r.status < 500;
} catch { return false; }
}
if (!(await workerUp('http://127.0.0.1:3777'))) await startWorker(); Try / catch
// Fire-and-forget pattern used by the plugin itself: attach .catch, filter the
// expected ECONNREFUSED (worker not started yet), surface everything else:
fetch(url, opts).catch((e: unknown) => {
const msg = e instanceof Error ? e.message : String(e);
if (!msg.includes('ECONNREFUSED')) console.warn('[my-plugin] POST failed:', msg);
}); Prevention
- Register the worker as a service/daemon so it auto-starts before OpenCode.
- Pin CLAUDE_MEM_WORKER_PORT/HOST explicitly in settings.json on multi-user machines (UID-derived defaults differ per user).
- Restart OpenCode after changing worker host/port — the plugin resolves WORKER_BASE_URL once at load.
- Keep plugin and worker on the same claude-mem version.
When it happens
Trigger: workerPostFireAndForget() with paths like session-observation endpoints while the worker crashes/restarts mid-request, while CLAUDE_MEM_WORKER_HOST resolves to a name with no DNS record, or while another process holds the configured port and immediately destroys the socket. Note WORKER_BASE_URL is computed once at plugin module load, so a port change after OpenCode started also lands here.
Common situations: Worker daemon restarted or upgraded while an OpenCode session stayed open; CLAUDE_MEM_WORKER_PORT changed in settings.json but OpenCode was not restarted, so the plugin still targets the old port now held by something else; firewall rules when the worker host is set to a non-loopback address.
Related errors
- [claude-mem] Worker GET ${path} failed: ${message}
- Server ${method} ${path} failed: ${message}
- [claude-mem] Worker GET ${path} returned ${response.status}
- `server ${commandLabel}` is a server runtime command, but CL
- Worker API error (${response.status}): ${errorText}
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/6f9edd27d0eb07db.
Report an issue: GitHub.