thedotmack/claude-mem · warning
Could not persist SessionEnd request for worker recovery
Error message
Could not persist SessionEnd request for worker recovery
What it means
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.
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
Example fix
// before
// queue dir unwritable silently
// after
mkdirSync(QUEUE_DIR, { recursive: true }); // ensure state dir exists before enqueue Defensive patterns
Strategy: try-catch
Validate before calling
const stateDir = path.join(os.homedir(), '.claude-mem');
if (!existsSync(stateDir)) mkdirSync(stateDir, { recursive: true });
accessSync(stateDir, fsConstants.W_OK); Try / catch
try {
enqueueDeferredSessionEnd({ contentSessionId: sessionId, platformSource });
} catch (e) {
logger.warn('HOOK', 'Could not persist SessionEnd request for worker recovery', { sessionId }, e instanceof Error ? e : new Error(String(e)));
// still return success — never block the session
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Worker unavailable, skipping hook
- Adapter rejected input
- Cannot lazy-spawn worker: worker-service.cjs not found in…
- Claude CLI preflight failed
- [claude-mem] Worker GET
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/5584b5c8f083216b.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/handlers/session-end.ts:59
contentSessionId: sessionId,
platformSource,
reason: input.reason,
cwd: input.cwd,
},
{
workerStartupTimeoutMs: SESSION_END_WORKER_STARTUP_TIMEOUT_MS,
timeoutMs: SESSION_END_REQUEST_TIMEOUT_MS,
},
);
if (isWorkerFallback(result)) {
try {
enqueueDeferredSessionEnd({ contentSessionId: sessionId, platformSource });
logger.debug('HOOK', 'Session-end request persisted for worker recovery', {
sessionId,
platformSource,
});
} catch (error) {
logger.warn('HOOK', 'Could not persist SessionEnd request for worker recovery', {
sessionId,
platformSource,
}, error instanceof Error ? error : new Error(String(error)));
}
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
}
logger.debug('HOOK', 'Session-end request queued, exiting hook');
return { continue: true, suppressOutput: true, exitCode: HOOK_EXIT_CODES.SUCCESS };
},
};
View on GitHub (pinned to d8bc9755e7)