BigPizzaV3/CodexPlusPlus · error
API 输出达到长度上限,本批未提交;请使用输出容量更大的模型
Error message
API 输出达到长度上限,本批未提交;请使用输出容量更大的模型
What it means
completionText() inspects choices[0].finish_reason of the Chat Completions response; when it equals 'length' the model hit its max output token limit mid-JSON, so the batch result would be truncated and unsafe to merge. The library refuses to commit the batch and asks for a model with a larger output capacity.
Solutions
- Switch to a model with larger output capacity (the error message's own advice), or reduce the batch size so the JSON fits
- If your proxy/provider allows, raise max_completion_tokens/max_tokens in the request configuration
- Split the conversation into smaller batches so each response fits within the output limit
- Check the response's usage.completion_tokens to confirm it equals the limit and adjust accordingly
Example fix
// before
const body = await chat({model:'small-4k-model', messages});
const text = completionText(body); // throws finish_reason=length
// after
const body = await chat({model:'large-output-model', max_completion_tokens: 16384, messages});
const text = completionText(body); Defensive patterns
Strategy: fallback
Validate before calling
if (body?.choices?.[0]?.finish_reason === 'length') {
const used = body?.usage?.completion_tokens;
console.warn(`output truncated at ${used} tokens — reduce batch size or raise max_completion_tokens`);
} Type guard
function isTruncated(body) { return body?.choices?.[0]?.finish_reason === 'length'; } Try / catch
try { text = completionText(body); }
catch (e) {
if (String(e).includes('长度上限')) return retryWithSmallerBatch();
throw e;
} Prevention
- Set max_completion_tokens comfortably above the expected batch JSON size
- Prefer models with >=16k output for large batch upserts (up to 48 nodes)
- Monitor usage.completion_tokens against your configured limit
- Reduce the number of parts per batch when responses repeatedly hit the cap
When it happens
Trigger: The external API returns a response with choices[0].finish_reason==='length'; typically when a 48-upsert batch exceeds the model's max_completion_tokens, or the request set max_tokens too low.
Common situations: Using small-context/low-output models (e.g. 4k-output variants) for large batches; provider default max output smaller than the batch JSON; user set a low max_tokens override in a proxy.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- API 未返回有效的 choices[0].message.content,请确认兼容 Chat Completions
- API 未能生成本批整理结果
- API 输出达到长度上限,本批未提交;请使用输出容量更大的模型
- 历史消息接口返回格式无效
- 整理侧边对话尚未创建完成
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/8cc5ac34ba674f1e.
Report an issue: GitHub.
Appendix: source
Thrown at tools/conversation-canvas/external-api.mjs:78
const part=await waitForApi(reader.read(),signal);if(part.done)break;
size+=part.value.byteLength;if(size>4*1024*1024)throw Object.assign(Error('API 响应超过大小限制'),{canvasApiLocal:true});
const text=decoder.decode(part.value,{stream:true});
if(!sse){raw+=text;if(/^\s*(data:|:)/.test(raw)){sse=true;buffer=raw;raw='';}}
else buffer+=text;
if(sse){let end;while((end=buffer.indexOf('\n'))>=0){consume(buffer.slice(0,end).replace(/\r$/,''));buffer=buffer.slice(end+1);}}
progress({bytes:size,chars:content.length});if(done)break;
}
const tail=decoder.decode();if(sse){buffer+=tail;if(buffer.trim())consume(buffer.replace(/\r$/,''));
if(!done&&!finish)throw Object.assign(Error('API 流式连接提前结束,本批未提交'),{canvasApiLocal:true,retryable:true});
return {choices:[{finish_reason:finish,message:{content}}]};
}
try{return JSON.parse(raw+tail);}catch{throw Object.assign(Error('API 返回的不是 JSON,请检查 API 地址'),{canvasApiLocal:true});}
}finally{void reader.cancel().catch(()=>{});try{reader.releaseLock();}catch{}}
}
export function completionText(body){
const choice=body?.choices?.[0];
if(choice?.finish_reason==='length')throw Error('API 输出达到长度上限,本批未提交;请使用输出容量更大的模型');
if(choice?.finish_reason==='content_filter'||choice?.message?.refusal)throw Error('API 未能生成本批整理结果');
const content=choice?.message?.content;
const value=typeof content==='string'?content:Array.isArray(content)?content.filter(p=>p?.type==='text').map(p=>p.text||'').join(''):'';
if(!value.trim())throw Error('API 未返回有效的 choices[0].message.content,请确认兼容 Chat Completions');
return value;
}
export function waitForApi(promise,signal){
signal?.throwIfAborted();
if(!signal)return promise;
return new Promise((resolve,reject)=>{
const abort=()=>{signal.removeEventListener('abort',abort);reject(signal.reason||new DOMException('Aborted','AbortError'));};
signal.addEventListener('abort',abort,{once:true});
promise.then(value=>{signal.removeEventListener('abort',abort);resolve(value);},error=>{signal.removeEventListener('abort',abort);reject(error);});
});
}
export function createApiOrganizer({request,timeoutMs=300000,maxRetries=2,retryDelayMs=2000}){View on GitHub (pinned to b1ed92e5e4)