thedotmack/claude-mem · warning
Shutdown request returned error
Error message
Shutdown request returned error
What it means
httpShutdown POSTs to the worker's /api/admin/shutdown endpoint (with ?reason=restart on the restart path) to stop or restart it. This warning means the HTTP round trip completed but the endpoint answered with a non-OK status, so the worker did not acknowledge shutdown through this path. The function returns false, letting callers fall back to PID/signal-based termination.
Source
Thrown at src/services/infrastructure/HealthMonitor.ts:134
export async function waitForPortFree(port: number, timeoutMs: number = 10000): Promise<boolean> {
const start = Date.now();
while (Date.now() - start < timeoutMs) {
if (!(await isPortInUse(port))) return true;
await new Promise(r => setTimeout(r, 500));
}
return false;
}
export async function httpShutdown(port: number, reason: 'stop' | 'restart' = 'stop'): Promise<boolean> {
try {
// The CLI restart path stops the worker through this same endpoint; the
// reason tag lets the worker report shutdown_reason: 'restart' on its
// worker_stopped telemetry instead of a generic 'stop'.
const endpointPath = reason === 'restart' ? '/api/admin/shutdown?reason=restart' : '/api/admin/shutdown';
const result = await httpRequestToWorker(port, endpointPath, 'POST');
if (!result.ok) {
logger.warn('SYSTEM', 'Shutdown request returned error', { status: result.statusCode });
return false;
}
return true;
} catch (error) {
if (error instanceof Error && error.message?.includes('ECONNREFUSED')) {
logger.debug('SYSTEM', 'Worker already stopped', {}, error);
return false;
}
logger.error('SYSTEM', 'Shutdown request failed unexpectedly', {}, error as Error);
return false;
}
}
export async function getRunningWorkerVersion(port: number): Promise<string | null> {
try {
const result = await httpRequestToWorker(port, '/api/health');
if (!result.ok) return null;
const data = JSON.parse(result.body) as { version: string };View on GitHub (pinned to e2d1df569a)
Solutions
- Read the logged status: 404 → version/endpoint mismatch, 401/403 → auth mismatch, 500 → the worker's shutdown handler failed (check worker logs).
- Verify CLI and worker come from the same claude-mem version (upgrade/downgrade so endpoint names match).
- Align admin auth configuration (token env/config) between the caller and the worker.
- If HTTP shutdown keeps failing, use the PID-based stop path (ProcessManager) as the documented fallback.
Defensive patterns
Strategy: retry
Validate before calling
// confirm the worker is listening and the endpoint exists before posting
const health = await httpRequestToWorker(port, '/api/health', 'GET');
if (!health.ok) {
throw new Error(`worker not reachable or wrong version on port ${port}`);
}
const ok = await httpShutdown(port, 'restart'); Try / catch
try {
const ok = await httpShutdown(port, 'restart');
if (!ok) await stopByPid(); // documented signal-based fallback
} catch (e) {
if (e instanceof Error && e.message.includes('ECONNREFUSED')) {
// worker already gone: treat as stopped
} else throw e;
} Prevention
- Keep CLI and worker on the same claude-mem version.
- Align admin auth tokens between caller and worker.
- Always implement the PID-based stop as the fallback when HTTP shutdown returns false.
When it happens
Trigger: POST /api/admin/shutdown returns 4xx/5xx: 401/403 when auth blocks the admin route, 404 when the CLI and worker versions disagree on the endpoint's existence, 500 when the worker's shutdown handler itself crashes.
Common situations: CLI `claude-mem restart` against an older or newer worker with a changed admin API; admin auth token mismatch between CLI and worker; a reverse proxy in front of the worker rewriting or blocking the route.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Worker API error (${response.status}): ${errorText}
- [uninstall] Worker shutdown attempt failed:
- [claude-mem] Worker GET ${path} returned ${response.status}
- Port did not free up after shutdown
- Shutdown already in progress — ignoring re-entrant shutdown
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/323e66739fd15152.
Report an issue: GitHub.