Summary
When the OpenClaw gateway process is terminated (SIGTERM/SIGINT/kill) or restarted, session_end hooks are never fired for currently active sessions. This leaves sessions in an incomplete state in any downstream system that relies on session lifecycle hooks (e.g., claude-mem plugin).
Root Cause
session_end is only fired when a new session starts and the previous session ID differs (in auth-profiles module, around line 193458-193468):
if (previousSessionEntry?.sessionId && previousSessionEntry.sessionId !== effectiveSessionId) {
hookRunner.runSessionEnd(payload.event, payload.context).catch(() => {});
}
When the gateway process is killed:
- No graceful shutdown handler iterates over active sessions
- No
session_end hooks fire
- On restart, the gateway has no memory of previous sessions
- New sessions are created without closing the old ones
Impact
- Downstream systems (e.g., claude-mem) accumulate ghost sessions in
active state
- Gateway restarts during development/debugging compound the problem (each restart adds more orphaned sessions)
- In our case: 11 orphaned sessions caused agent pool exhaustion with 63 timeout errors in a single day
Expected Behavior
On gateway shutdown (SIGTERM/SIGINT), the process should:
- Iterate over all active sessions
- Fire
session_end for each
- Then exit
Or alternatively, provide a mechanism for plugins to register shutdown handlers.
Workaround
We've added a cron-based cleanup that marks stale active sessions as completed in the database. This is a band-aid, not a fix.
Environment
- OpenClaw version: latest stable (installed via npm)
- Platform: WSL2 (Linux)
Summary
When the OpenClaw gateway process is terminated (SIGTERM/SIGINT/kill) or restarted,
session_endhooks are never fired for currently active sessions. This leaves sessions in an incomplete state in any downstream system that relies on session lifecycle hooks (e.g., claude-mem plugin).Root Cause
session_endis only fired when a new session starts and the previous session ID differs (inauth-profilesmodule, around line 193458-193468):When the gateway process is killed:
session_endhooks fireImpact
activestateExpected Behavior
On gateway shutdown (SIGTERM/SIGINT), the process should:
session_endfor eachOr alternatively, provide a mechanism for plugins to register shutdown handlers.
Workaround
We've added a cron-based cleanup that marks stale active sessions as completed in the database. This is a band-aid, not a fix.
Environment