{"record":{"id":"5584b5c8f083216b","repo":"thedotmack/claude-mem","slug":"could-not-persist-sessionend-request-for-worker-recovery","errorCode":null,"errorMessage":"Could not persist SessionEnd request for worker recovery","messagePattern":"Could not persist SessionEnd request for worker recovery","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/cli/handlers/session-end.ts","lineNumber":59,"sourceCode":"        contentSessionId: sessionId,\n        platformSource,\n        reason: input.reason,\n        cwd: input.cwd,\n      },\n      {\n        workerStartupTimeoutMs: SESSION_END_WORKER_STARTUP_TIMEOUT_MS,\n        timeoutMs: SESSION_END_REQUEST_TIMEOUT_MS,\n      },\n    );\n    if (isWorkerFallback(result)) {\n      try {\n        enqueueDeferredSessionEnd({ contentSessionId: sessionId, platformSource });\n        logger.debug('HOOK', 'Session-end request persisted for worker recovery', {\n          sessionId,\n          platformSource,\n        });\n      } catch (error) {\n        logger.warn('HOOK', 'Could not persist SessionEnd request for worker recovery', {\n          sessionId,\n          platformSource,\n        }, error instanceof Error ? error : new Error(String(error)));\n      }\n      return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };\n    }\n\n    logger.debug('HOOK', 'Session-end request queued, exiting hook');\n    return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };\n  },\n};\n","sourceCodeStart":41,"sourceCodeEnd":71,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/cli/handlers/session-end.ts#L41-L71","documentation":"On SessionEnd, when the worker cannot be reached immediately, the handler attempts to enqueue a deferred SessionEnd request so the worker can recover it later. If that persistence itself throws, this warning is logged. Crucially the hook still returns success ({ continue: true, exitCode: SUCCESS }) so the Claude Code session is never blocked — the cost is only a potentially lost session-end event.","triggerScenarios":"enqueueDeferredSessionEnd throws — e.g. the queue/persistence directory is unwritable, disk full, DB locked, or the persistence layer throws on serialize. Raised during execute() of the SessionEnd hook while the worker is unavailable.","commonSituations":"Full disk or ~/.claude-mem directory permission problems; SQLite lock contention from another worker; corrupted queue store; running the hook in a sandbox without write access to the state dir.","solutions":["Check ~/.claude-mem exists and is writable by the current user","Free disk space if ENOSPC appears in the attached error","Restart/rebuild the worker (npm run build-and-sync) so future SessionEnd events are delivered directly instead of deferred","Clear a corrupted/locked queue store so persistence can succeed again"],"exampleFix":"// before\n// queue dir unwritable silently\n// after\nmkdirSync(QUEUE_DIR, { recursive: true }); // ensure state dir exists before enqueue","handlingStrategy":"try-catch","validationCode":"const stateDir = path.join(os.homedir(), '.claude-mem');\nif (!existsSync(stateDir)) mkdirSync(stateDir, { recursive: true });\naccessSync(stateDir, fsConstants.W_OK);","typeGuard":null,"tryCatchPattern":"try {\n  enqueueDeferredSessionEnd({ contentSessionId: sessionId, platformSource });\n} catch (e) {\n  logger.warn('HOOK', 'Could not persist SessionEnd request for worker recovery', { sessionId }, e instanceof Error ? e : new Error(String(e)));\n  // still return success — never block the session\n}","preventionTips":["Ensure ~/.claude-mem exists and is writable","Monitor disk space on machines running hooks","Keep the worker healthy so deferral is rarely needed","Alert on this warning — it means a session-end event may be lost"],"tags":["hook","persistence","worker","session-end"],"backgroundTag":"file-write-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"}