BigPizzaV3/CodexPlusPlus · warning · Error
本批整理中断,已完成批次已保存,可点击继续
Error message
本批整理中断,已完成批次已保存,可点击继续
What it means
The background long-conversation organizer session polls a native turn; if that turn ends with status other than 'completed' or carries an error, the session is reset to 'ready', already-completed batches are persisted via save(), and this error is thrown. It signals an interrupted batch rather than total failure — partial progress is safe and the user can click 'continue' to resume the remaining batches.
Solutions
- Click the 'continue' button on the canvas: session.phase is 'ready' and completed batches are already saved, so re-processing will resume from the un-submitted batch
- Check the native turn's error (turn.error) for the root cause (network, quota, auth) and fix that first
- Verify manager.getConversation(session.sideId) still returns the conversation before continuing; if the session was invalidated, restart the organizer from scratch
- Retry with smaller batches or a more reliable model if the batch output keeps failing
Example fix
// before
await organizer.runAll(); // throws and stops the whole run
// after
try { await organizer.runAll(); }
catch (e) {
if (/已完成批次已保存/.test(String(e))) await organizer.resume(); // click continue equivalent
else throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
const conv = manager.getConversation(session.sideId);
if (!conv) throw new Error('session invalid');
const turn = nativeTurns(conv).find(t => t.turnId === session.turnId);
if (turn && turn.status !== 'inProgress' && (turn.status !== 'completed' || turn.error)) console.warn('batch will be interrupted'); Type guard
function isCompletedClean(turn) { return !!turn && turn.status === 'completed' && !turn.error; } Try / catch
try { await runBatch(); } catch (e) { if (String(e).includes('已完成批次已保存')) { showContinueButton(); } else { throw e; } } Prevention
- Check conversation validity (getConversation) before starting each batch
- Surface the native turn's error to the user instead of generic failures
- Persist state (save()) after every completed batch so interruption is resumable
- Use abort signals and handle them explicitly rather than letting turns die silently
When it happens
Trigger: nativeTurns(conversation) finds the turn with session.turnId and its status is neither 'inProgress' nor 'completed', or it is completed but turn.error is set; e.g. the native session/turn failed, errored out, or was aborted mid-batch.
Common situations: The underlying native conversation hit a rate limit or network failure mid-batch; the turn was cancelled by the user; the codex client crashed during the background organizer run; the conversation was recreated so the turn never completes cleanly.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- archived lookup task failed
- 后台整理会话已失效,已完成批次仍保留;点击继续可重新处理本批
- 等待 Codex 回复超时
- 登录超时。
- export markdown task failed
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/31ae2d40a40cbb31.
Report an issue: GitHub.
Appendix: source
Thrown at tools/conversation-canvas/src/native-sidechat.js:151
session.turnId=accepted.turnId;session.phase='waiting';await save();
}
if(session.requestId!==requestId||!session.turnId){
signal?.throwIfAborted();
Object.assign(session,{requestId,turnId:null,messageId:crypto.randomUUID(),phase:'submitting'});await save();
session.turnId=await native.Mr({scope,turnTrigger:'side_chat',manager,hostId,targetConversationId:session.sideId,cwd:parent.cwd,agentMode:'auto',permissionProfileId:null,shouldSendPermissionOverrides:false,activeCollaborationMode:mode,clientUserMessageId:session.messageId,
context:{prompt,collaborationMode:mode,workspaceRoots:[parent.cwd],imageAttachments:[],fileAttachments:[],addedFiles:[],commentAttachments:[],selectedTextAttachments:[],pastedTextAttachments:[],threadReferences:[]}});
session.phase='waiting';await save();
}
onProgress('GPT-5.6 Luna · 中 · 正在后台整理,可暂停后继续…');
// No fixed whole-job deadline: retain the turn identity when paused so that
// resume reads the existing response instead of launching duplicate work.
for(;;){
signal?.throwIfAborted();
const conversation=manager.getConversation(session.sideId);
if(!conversation)throw Error('后台整理会话已失效,已完成批次仍保留;点击继续可重新处理本批');
const turn=nativeTurns(conversation).find(t=>t.turnId===session.turnId);
if(turn&&turn.status!=='inProgress'){
if(turn.status!=='completed'||turn.error){session.requestId=null;session.turnId=null;session.phase='ready';await save();throw Error('本批整理中断,已完成批次已保存,可点击继续');}
if(session.phase!=='completed')session.batches=(session.batches||0)+1;
session.phase='completed';await save();
return turn.items.filter(i=>i.type==='agentMessage'&&(i.phase==null||i.phase==='final_answer')).map(i=>i.text??'').join('\n');
}
await new Promise(resolve=>setTimeout(resolve,1000));
}
}
View on GitHub (pinned to b1ed92e5e4)