BigPizzaV3/CodexPlusPlus · error · Error
会话接口返回了不匹配的数据
Error message
会话接口返回了不匹配的数据
What it means
In bridge-data.mjs's copy of graphFromExport, the second guard throws '会话接口返回了不匹配的数据' when result.kind !== 'codex-rollout', session_id doesn't match threadId, or content isn't a string. It protects the JSONL parser from unexpected payload shapes.
Solutions
- Route kind==='canvas-messages' results to the native branch instead of graphFromExport
- Align bridge-data.mjs and the host so codex-rollout results carry string content and matching session_id
- Re-sync so session_id and threadId agree
- Assert the shape in tests before parsing
Example fix
// before
if(result.kind!=='codex-rollout'||result.session_id!==threadId||typeof result.content!=='string')throw new Error('会话接口返回了不匹配的数据');
// after
if (result.kind==='canvas-messages') return fromNativeMessages(result, threadId, annotations);
if(result.kind!=='codex-rollout'||result.session_id!==threadId||typeof result.content!=='string')throw new Error('会话接口返回了不匹配的数据'); Defensive patterns
Strategy: type-guard
Validate before calling
const matches = (r, threadId) => r?.status==='ok' && r.kind==='codex-rollout' && r.session_id===threadId && typeof r.content==='string';
if (!matches(result, threadId)) throw new Error('会话接口返回了不匹配的数据'); Type guard
const isRolloutForThread = (r, threadId) => r?.kind==='codex-rollout' && r.session_id===threadId && typeof r.content==='string';
Try / catch
try { graph = graphFromExport(result, threadId, ann); } catch (e) { if (e.message==='会话接口返回了不匹配的数据') fallbackToNativeOrRefresh(); else throw e; } Prevention
- Dispatch on result.kind before calling the parser
- Assert payload shape in bridge integration tests
- Re-sync when threadId changes mid-request
When it happens
Trigger: sync passes a successful result whose kind is 'canvas-messages' (native shape) to graphFromExport, whose session_id differs from the requested thread, or whose content is missing/non-string.
Common situations: Bridge version skew changing the payload kind; native paginated read path returning canvas-messages; thread switched between request and response; truncated response without content.
Related errors
- 会话接口返回了不匹配的数据
- 记录中的任务 ID 与当前任务不一致
- 记录中的任务 ID 与当前任务不一致
- result?.message||'Codex++ 会话读取失败'
- user-script runtime status must be a JSON object
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/65348606e40c7d8a.
Report an issue: GitHub.
Appendix: source
Thrown at tools/conversation-canvas/bridge-data.mjs:5
import {parseMessage,buildGraph} from './model.mjs';
export function graphFromExport(result, threadId, annotations={nodes:[]}) {
if(result?.status!=='ok')throw new Error(result?.message||'Codex++ 会话读取失败');
if(result.kind!=='codex-rollout'||result.session_id!==threadId||typeof result.content!=='string')throw new Error('会话接口返回了不匹配的数据');
const messages=[],seen=new Set();
let declaredId=null;
// Ignore an unfinished JSONL tail; the next refresh will read the completed line.
const lines=result.content.slice(0,result.content.lastIndexOf('\n')+1).split('\n');
for(let i=0;i<lines.length;i++){
if(!lines[i].trim())continue;
let r;try{r=JSON.parse(lines[i]);}catch{continue;}
if(r.type==='session_meta')declaredId=r.payload?.id;
const m=parseMessage(r,`message-${threadId}-line-${i}`);
if(m&&!seen.has(m.id)){seen.add(m.id);messages.push(m);}
}
if(declaredId&&declaredId!==threadId)throw new Error('记录中的任务 ID 与当前任务不一致');
return {threadId,title:annotations.title||'当前对话',messages,...buildGraph(messages,annotations)};
}
View on GitHub (pinned to b1ed92e5e4)