{"record":{"id":"e16670daaf0995c1","repo":"thedotmack/claude-mem","slug":"uninstall-worker-shutdown-attempt-failed","errorCode":null,"errorMessage":"[uninstall] Worker shutdown attempt failed:","messagePattern":"\\[uninstall\\] Worker shutdown attempt failed:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/npx-cli/commands/uninstall.ts","lineNumber":280,"sourceCode":"      initialValue: false,\n    });\n\n    if (p.isCancel(shouldContinue) || !shouldContinue) {\n      p.cancel('Uninstall cancelled.');\n      return;\n    }\n  }\n\n  const workerPort = SettingsDefaultsManager.get('CLAUDE_MEM_WORKER_PORT');\n  try {\n    const result = await shutdownWorkerAndWait(workerPort, 10000);\n    if (result.workerWasRunning && result.stopped) {\n      p.log.info('Worker service stopped.');\n    } else if (result.workerWasRunning) {\n      p.log.warn('Worker service did not confirm shutdown; continuing uninstall cleanup.');\n    }\n  } catch (error: unknown) {\n    console.warn('[uninstall] Worker shutdown attempt failed:', error instanceof Error ? error.message : String(error));\n  }\n\n  // #2568 — server-runtime teardown. Gated on the installed/selected runtime so\n  // the worker uninstall path is completely unchanged. The bundled Docker\n  // compose stack lives under the marketplace dir; if it's present we treat the\n  // stack as locally managed and instruct teardown (the actual `docker compose\n  // down -v` is an operator/CI side effect, not run from this Node process).\n  const selectedRuntime = readSelectedRuntime();\n  if (selectedRuntime === 'server') {\n    if (existsSync(join(marketplaceDirectory(), 'docker-compose.yml'))) {\n      p.log.info(\n        'Server runtime detected. Tear down the bundled stack with '\n          + '`docker compose down -v --remove-orphans` (stops + removes pg + redis/valkey).',\n      );\n    } else {\n      p.log.info('Server runtime detected (externally managed stack — leaving Docker/pg/redis untouched).');\n    }\n    clearServerRuntimeSettings(SERVER_RUNTIME_SETTINGS_KEYS);","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/npx-cli/commands/uninstall.ts#L262-L298","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before (worker hung, graceful stop times out)\nawait stopWorker(); // throws timeout\n// after (force kill fallback)\ntry { await stopWorker(); }\ncatch { execSync(`kill -9 $(pgrep -f claude-mem.*worker) || true`); }","handlingStrategy":"try-catch","validationCode":"const workerRunning = typeof Bun !== 'undefined'\n  ? Bun.spawnSync(['pgrep', '-f', 'claude-mem.*worker']).exitCode === 0\n  : false;\nif (!workerRunning) console.log('Worker not running; skipping shutdown');","typeGuard":"function isSpawnError(e: unknown): e is NodeJS.ErrnoException {\n  return e instanceof Error && 'code' in e && ['ENOENT','EACCES','ETIMEDOUT'].includes((e as NodeJS.ErrnoException).code ?? '');\n}","tryCatchPattern":"try {\n  await stopWorker();\n} catch (e) {\n  console.warn(`Graceful stop failed (${isSpawnError(e) ? e.code : e}) — falling back to kill -9`);\n  execSync('pkill -9 -f claude-mem.*worker || true');\n}","preventionTips":["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."],"tags":["worker","process-management","uninstall","shutdown"],"backgroundTag":"worker-shutdown-failed","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}