fix: recover from stale Claude Code session IDs instead of retrying infinitely

When Claude Code exits with code 1 during a session resume, the group's
session ID is now cleared from the database and the query is retried with
a fresh session. This prevents the infinite retry loop that occurred when
a stale/corrupt session ID was stored in SQLite.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Gary Walker
2026-03-30 16:09:56 +11:00
parent 54a8648c95
commit 474346e214
2 changed files with 50 additions and 0 deletions
+4
View File
@@ -526,6 +526,10 @@ export function setSession(groupFolder: string, sessionId: string): void {
).run(groupFolder, sessionId);
}
export function deleteSession(groupFolder: string): void {
db.prepare('DELETE FROM sessions WHERE group_folder = ?').run(groupFolder);
}
export function getAllSessions(): Record<string, string> {
const rows = db
.prepare('SELECT group_folder, session_id FROM sessions')
+46
View File
@@ -30,6 +30,7 @@ import {
getAllChats,
getAllRegisteredGroups,
getAllSessions,
deleteSession,
getAllTasks,
getMessagesSince,
getNewMessages,
@@ -355,6 +356,51 @@ async function runAgent(
}
if (output.status === 'error') {
// Detect stale/corrupt session: container failed while resuming an existing session.
// Clear the session and retry once with a fresh session to avoid infinite retry loops.
if (sessionId) {
logger.warn(
{ group: group.name, staleSessionId: sessionId, error: output.error },
'Container failed with existing session — clearing stale session and retrying with fresh session',
);
delete sessions[group.folder];
deleteSession(group.folder);
const freshOutput = await runContainerAgent(
group,
{
prompt,
sessionId: undefined,
groupFolder: group.folder,
chatJid,
isMain,
assistantName: ASSISTANT_NAME,
},
(proc, containerName) =>
queue.registerProcess(chatJid, proc, containerName, group.folder),
wrappedOnOutput,
);
if (freshOutput.newSessionId) {
sessions[group.folder] = freshOutput.newSessionId;
setSession(group.folder, freshOutput.newSessionId);
}
if (freshOutput.status === 'error') {
logger.error(
{ group: group.name, error: freshOutput.error },
'Container agent error on fresh session retry',
);
return 'error';
}
logger.info(
{ group: group.name, newSessionId: freshOutput.newSessionId },
'Fresh session retry succeeded',
);
return 'success';
}
logger.error(
{ group: group.name, error: output.error },
'Container agent error',