fix: auto-fallback to fresh conversation when SDK session resume fails
When continuing an old chat session, CodePilot passes the stored sdk_session_id to the SDK with resume=true. If the local SDK session file is stale, corrupt, or incompatible (e.g. after a CLI version update), the SDK process exits with code 1 and the user sees a misleading "Invalid or missing API Key" error. This fix wraps the initial query() call with a try-catch that detects resume failures by peeking at the first async message. On failure, it automatically retries without the resume option, starting a fresh SDK session while preserving the chat history in CodePilot. - src/lib/claude-client.ts: added resume-failure detection and automatic fallback logic around the query() call
This commit is contained in:
1 parent
979e1b1973
commit
61e093094e
1 file changed
+31
-1
@@ -533,11 +533,41 @@ export function streamClaude(options: ClaudeStreamOptions): ReadableStream<strin
|
||||
}
|
||||
}
|
||||
|
||||
const conversation = query({
|
||||
// Try to start the conversation. If resuming a previous session fails
|
||||
// (e.g. stale/corrupt session file, CLI version mismatch), automatically
|
||||
// fall back to starting a fresh conversation without resume.
|
||||
let conversation = query({
|
||||
prompt: finalPrompt,
|
||||
options: queryOptions,
|
||||
});
|
||||
|
||||
// Wrap the iterator so we can detect resume failures on the first message
|
||||
if (sdkSessionId) {
|
||||
try {
|
||||
// Peek at the first message to verify resume works
|
||||
const iter = conversation[Symbol.asyncIterator]();
|
||||
const first = await iter.next();
|
||||
|
||||
// Re-wrap into an async iterable that yields the first message then the rest
|
||||
conversation = (async function* () {
|
||||
if (!first.done) yield first.value;
|
||||
while (true) {
|
||||
const next = await iter.next();
|
||||
if (next.done) break;
|
||||
yield next.value;
|
||||
}
|
||||
})() as ReturnType<typeof query>;
|
||||
} catch (resumeError) {
|
||||
console.warn('[claude-client] Resume failed, retrying without resume:', resumeError instanceof Error ? resumeError.message : resumeError);
|
||||
// Remove resume and try again as a fresh conversation
|
||||
delete queryOptions.resume;
|
||||
conversation = query({
|
||||
prompt: finalPrompt,
|
||||
options: queryOptions,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
registerConversation(sessionId, conversation);
|
||||
|
||||
let lastAssistantText = '';
|
||||
|
||||
Reference in new issue
Block a user