BigPizzaV3/CodexPlusPlus · error · Error
本批整理中断,已完成批次已保存,可点击继续
Error message
本批整理中断,已完成批次已保存,可点击继续
What it means
The polling loop found the tracked turn with a terminal status that is not a clean completion: status !== 'completed' or turn.error is set. The code resets requestId/turnId and phase to 'ready' (so clicking continue resubmits this batch) and throws. Completed batches already counted remain saved.
Solutions
- Click 继续 to retry the failed batch; state was reset to 'ready' so it will resubmit.
- Inspect the side conversation's turn error in the Codex UI for the underlying cause.
- If the model keeps erroring, switch organizer model/effort or use the external API mode with a different provider.
- Retry after a wait if the cause was rate limiting or a transient backend error.
Example fix
// before
if(turn.status!=='completed'||turn.error){ ...throw Error('本批整理中断,已完成批次已保存,可点击继续'); }
// after
if(turn.status!=='completed'||turn.error){
if(++batchRetries<3) return retryBatch(); // auto-retry with backoff
...throw Error('本批整理中断,已完成批次已保存,可点击继续');
} Defensive patterns
Strategy: retry
Validate before calling
const turn = nativeTurns(conversation).find(t => t.turnId === session.turnId); const healthy = turn && turn.status === 'completed' && !turn.error;
Type guard
const turnSucceeded = (t) => t?.status === 'completed' && !t?.error;
Try / catch
try { await nativeSideChat(...); } catch (e) { if (e.message.includes('整理中断')) { await backoff(); retryBatch(); } else throw e; } Prevention
- Inspect turn.error to distinguish model errors from cancellations before retrying.
- Cap retries per batch with exponential backoff to survive transient backend errors.
- Switch organizer model/provider if a specific model keeps failing.
When it happens
Trigger: Turn finished as 'failed'/'aborted', or completed with a non-empty turn.error — model error, permission denial inside the side task, or the turn was cancelled.
Common situations: Model refused/errored on the batch prompt; the side turn was aborted when the user paused or the app suspended; rate limiting or backend error on the model (gpt-5.6-luna) endpoint.
Related errors
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/7f0e65829f238b0a.
Report an issue: GitHub.
Appendix: source
Thrown at tools/conversation-canvas/public/canvas.user.js:611
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));
}
}
// OpenAI-compatible Chat Completions. Never persist credentials in tree checkpoints.
function apiEndpoint(raw){
let url;try{url=new URL(String(raw).trim());}catch{throw Error('请输入完整的 HTTPS API 地址');}
if(url.protocol!=='https:'||url.username||url.password||url.search||url.hash)throw Error('API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段');
const path=url.pathname.replace(/\/+$/,'');
url.pathname=path.endsWith('/chat/completions')?path:(path||'/v1')+'/chat/completions';
return url.href;
}
function apiConfig(input){View on GitHub (pinned to b1ed92e5e4)