fix: clear stale sdk_session_id on mid-stream crash to prevent repeated failures

When a resumed SDK session crashes mid-stream (after outputting some
content), the sdk_session_id remains in the database. Every subsequent
message in that chat session attempts to resume the same broken SDK
session, causing repeated failures.

Root cause: the SDK process starts successfully with resume, outputs
some content, then crashes (exit code 1). The sdk_session_id was
already stored from a previous successful turn and never gets cleared
on error.

Fix: in the catch block of streamClaude(), when we were resuming a
session (sdkSessionId is set), clear the sdk_session_id in the
database. This ensures the next message starts a fresh SDK session
instead of repeatedly hitting the same broken resume.

Combined with the earlier peek-based fallback (which handles failures
at startup), this covers both failure modes:
1. Resume fails immediately → fallback retries without resume in the
   same request
2. Resume fails mid-stream → clears sdk_session_id so the NEXT
   request starts fresh

- src/lib/claude-client.ts: import updateSdkSessionId, add
  sdk_session_id reset in catch block when sdkSessionId was set
This commit is contained in:
7418 committed 2026-02-24 17:56:38 +08:00
1 parent 481f218474
commit f871087a84
1 file changed
+14 -1
+14 -1
View File
@@ -19,7 +19,7 @@ import type { ClaudeStreamOptions, SSEEvent, TokenUsage, MCPServerConfig, Permis
import { isImageFile } from '@/types';
import { registerPendingPermission } from './permission-registry';
import { registerConversation, unregisterConversation } from './conversation-registry';
import { getSetting, getActiveProvider } from './db';
import { getSetting, getActiveProvider, updateSdkSessionId } from './db';
import { findClaudeBinary, findGitBash, getExpandedPath } from './platform';
import os from 'os';
import fs from 'fs';
@@ -747,6 +747,19 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream<strin
controller.enqueue(formatSSE({ type: 'error', data: errorMessage }));
controller.enqueue(formatSSE({ type: 'done', data: '' }));
// If we were resuming a session and it crashed mid-stream, clear the
// stale sdk_session_id so the next message starts a fresh SDK session
// instead of repeatedly hitting the same broken resume.
if (sdkSessionId && sessionId) {
try {
updateSdkSessionId(sessionId, '');
console.warn('[claude-client] Cleared stale sdk_session_id for session', sessionId);
} catch {
// best effort
}
}
controller.close();
} finally {
unregisterConversation(sessionId);