openclaw/openclaw · error
Codex settled-turn finalization returned unexpected native i
Error message
Codex settled-turn finalization returned unexpected native item: ${unexpectedItem.type} What it means
Thrown when iterating the finalizer's bounded-turn output items and encountering an item whose type is not in FINALIZER_PASSIVE_ITEM_TYPES (agentMessage, reasoning) and not the prompt-echo userMessage. The finalizer is instructed to produce a single text answer with no external capabilities (requireNoExternalCapabilities: true), so any function_call, tool call, or stray userMessage is treated as a contract violation.
Source
Thrown at extensions/codex/src/app-server/settled-turn-finalizer.ts:80
}
if (item.type === "userMessage" && !promptEchoSeen) {
const content = Array.isArray(item.content) ? item.content : [];
const input = content[0];
const isPromptEcho =
content.length === 1 &&
isJsonObject(input) &&
input.type === "text" &&
input.text === attempt.prompt;
if (isPromptEcho) {
promptEchoSeen = true;
continue;
}
}
unexpectedItem = item;
break;
}
if (unexpectedItem) {
throw new Error(
`Codex settled-turn finalization returned unexpected native item: ${unexpectedItem.type}`,
);
}
const text = bounded.text.trim();
if (!text) {
return {
assistant: createAssistantMessage(attempt, "", {
tokenUsage: bounded.usage,
aborted: false,
promptError: null,
}),
...(bounded.usage ? { usage: bounded.usage } : {}),
};
}
if (isSilentReplyText(text)) {
throw new Error("Codex settled-turn finalization completed without a visible answer");
}
View on GitHub (pinned to 01804a7531)
Solutions
- Inspect bounded.items to see the unexpected item type and payload; the message includes the type.
- Confirm the bounded turn was launched with requireNoExternalCapabilities: true and isolation: "private-stdio".
- If the protocol added a new passive item type, add it to FINALIZER_PASSIVE_ITEM_TYPES after confirming it carries no executable capability.
- Tighten FINALIZER_DEVELOPER_INSTRUCTIONS or switch model if the finalizer persistently emits tool calls.
Example fix
// before const FINALIZER_PASSIVE_ITEM_TYPES = new Set(["agentMessage", "reasoning"]); // item.type === "function_call" -> throws // after (protocol added reasoning summary, verified non-executable) const FINALIZER_PASSIVE_ITEM_TYPES = new Set(["agentMessage", "reasoning", "reasoningSummary"]);
Defensive patterns
Strategy: validation
Validate before calling
const FINALIZER_ALLOWED_ITEM_TYPES = new Set(["agentMessage", "reasoning", "userMessage"]);
function assertFinalizerItemsAcceptable(items: ReadonlyArray<{ type: string }>): void {
for (const item of items) {
if (!FINALIZER_ALLOWED_ITEM_TYPES.has(item.type)) {
throw new Error(`Finalizer produced disallowed item type up front: ${item.type}`);
}
}
}
// run after bounded.items returns, before runCodexSettledTurnFinalization proceeds
assertFinalizerItemsAcceptable(bounded.items); Type guard
function isPassiveFinalizerItem(item: { type: string }): boolean {
return item.type === "agentMessage" || item.type === "reasoning";
}
function isPromptEchoUserMessage(item: { type: string; content?: unknown }, prompt: string): boolean {
if (item.type !== "userMessage" || !Array.isArray(item.content) || item.content.length !== 1) return false;
const c = item.content[0] as { type?: string; text?: unknown };
return c?.type === "text" && c.text === prompt;
} Try / catch
try {
return await runCodexSettledTurnFinalization(operation, options);
} catch (err) {
if (err instanceof Error && err.message.startsWith("Codex settled-turn finalization returned unexpected native item")) {
// The model ignored requireNoExternalCapabilities; re-run with stricter instructions or different model.
logger.error({ itemType: err.message }, "finalizer produced unexpected item");
}
throw err;
} Prevention
- Always launch the finalizer with requireNoExternalCapabilities: true and isolation: "private-stdio".
- If a new passive item type appears in the protocol, verify it carries no capability before adding it to FINALIZER_PASSIVE_ITEM_TYPES.
- Monitor finalizer item types on model changes; a model that starts emitting function_call is a regression.
When it happens
Trigger: The finalizer model emits a function_call or function_call_output despite requireNoExternalCapabilities; the model echoes something other than the prompt as a userMessage; a reasoning/agentMessage item is missing its type tag due to a protocol parsing drift.
Common situations: Model regression where the finalizer ignores developer instructions and tries to call a tool; app-server protocol change that renames an item type; prompt that the model parrots back in a non-echo userMessage slot.
Related errors
- Codex settled-turn finalization completed without a visible
- Codex settled-turn finalization context is unavailable
- Codex settled-turn final answer transcript attestation misma
- Codex structured extraction returned invalid JSON.
- Codex structured extraction JSON did not match schema: ${mes
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/5a24b8d800c0d381.
Report an issue: GitHub.