thedotmack/claude-mem · warning
[uninstall] Worker shutdown attempt failed:
Error message
[uninstall] Worker shutdown attempt failed:
What it means
runUninstallCommand tries to stop the claude-mem background worker service before cleanup. Any error thrown by that shutdown attempt (missing worker command, IPC failure, timeout) is caught and reported with this warning; the uninstall explicitly continues, leaving the worker possibly running. Follow-up warnings tell the user shutdown was not confirmed.
Solutions
- Stop the worker manually: npx claude-mem worker stop (or kill the claude-mem worker process via ps/Task Manager).
- Re-run uninstall after stopping the worker so cleanup sees no running processes.
- If the worker is wedged, force-kill it (kill -9 <pid> / End Task) and re-run uninstall.
- Check that the installed plugin files are intact — a corrupted install can break the stop command; reinstall then uninstall.
Example fix
// before (worker hung, graceful stop times out)
await stopWorker(); // throws timeout
// after (force kill fallback)
try { await stopWorker(); }
catch { execSync(`kill -9 $(pgrep -f claude-mem.*worker) || true`); } Defensive patterns
Strategy: try-catch
Validate before calling
const workerRunning = typeof Bun !== 'undefined'
? Bun.spawnSync(['pgrep', '-f', 'claude-mem.*worker']).exitCode === 0
: false;
if (!workerRunning) console.log('Worker not running; skipping shutdown'); Type guard
function isSpawnError(e: unknown): e is NodeJS.ErrnoException {
return e instanceof Error && 'code' in e && ['ENOENT','EACCES','ETIMEDOUT'].includes((e as NodeJS.ErrnoException).code ?? '');
} Try / catch
try {
await stopWorker();
} catch (e) {
console.warn(`Graceful stop failed (${isSpawnError(e) ? e.code : e}) — falling back to kill -9`);
execSync('pkill -9 -f claude-mem.*worker || true');
} Prevention
- Keep the plugin fully updated so the worker entrypoint matches the stop command.
- Restart a hung worker (or reboot) before uninstalling rather than skipping the stop step.
- Verify the worker control socket/port is reachable (curl the health endpoint) before uninstall.
- In CI/containers, ensure the daemon can receive signals (PID 1 handling) before uninstall.
When it happens
Trigger: The stopWorker path throws inside its try: worker binary/entry not found (moved or partially deleted install), the worker's control socket/HTTP endpoint is unreachable, the process ignores SIGTERM and the call times out, or a spawn failure (ENOENT/EACCES).
Common situations: Half-updated installs where the worker entrypoint changed; worker hung or wedged after a crash; port/socket conflicts; running uninstall in an environment (CI container) where the worker daemon can't be signalled; permission issues spawning the worker stop command.
Related errors
- Worker service did not confirm shutdown; continuing…
- Worker shutdown attempt failed
- Graceful shutdown deadline exceeded — proceeding
- Shutdown already in progress — ignoring re-entrant shutdown…
- Shutdown request returned error
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/e16670daaf0995c1.
Report an issue: GitHub.
Appendix: source
Thrown at src/npx-cli/commands/uninstall.ts:280
initialValue: false,
});
if (p.isCancel(shouldContinue) || !shouldContinue) {
p.cancel('Uninstall cancelled.');
return;
}
}
const workerPort = SettingsDefaultsManager.get('CLAUDE_MEM_WORKER_PORT');
try {
const result = await shutdownWorkerAndWait(workerPort, 10000);
if (result.workerWasRunning && result.stopped) {
p.log.info('Worker service stopped.');
} else if (result.workerWasRunning) {
p.log.warn('Worker service did not confirm shutdown; continuing uninstall cleanup.');
}
} catch (error: unknown) {
console.warn('[uninstall] Worker shutdown attempt failed:', error instanceof Error ? error.message : String(error));
}
// #2568 — server-runtime teardown. Gated on the installed/selected runtime so
// the worker uninstall path is completely unchanged. The bundled Docker
// compose stack lives under the marketplace dir; if it's present we treat the
// stack as locally managed and instruct teardown (the actual `docker compose
// down -v` is an operator/CI side effect, not run from this Node process).
const selectedRuntime = readSelectedRuntime();
if (selectedRuntime === 'server') {
if (existsSync(join(marketplaceDirectory(), 'docker-compose.yml'))) {
p.log.info(
'Server runtime detected. Tear down the bundled stack with '
+ '`docker compose down -v --remove-orphans` (stops + removes pg + redis/valkey).',
);
} else {
p.log.info('Server runtime detected (externally managed stack — leaving Docker/pg/redis untouched).');
}
clearServerRuntimeSettings(SERVER_RUNTIME_SETTINGS_KEYS);View on GitHub (pinned to d8bc9755e7)