Bug: MCP tool-call meta serialization failure silently drops sandbox state
What version of Codex CLI is running?
Reproduced with codex-cli 0.145.0. The same implementation is still present in main at e4fb5311d7468839def62eabda4b268f4a54cf11.
What platform is your computer?
Darwin 26.5.2 arm64 arm (macOS).
What issue are you seeing?
When an MCP tool call returns a meta field that cannot be serialized to JSON, the meta is silently set to None instead of propagating an error. This can cause the sandbox policy to fall back to a default when the meta contains sandbox state information (codex/sandbox-state-meta).
Affected code locations:
codex-mcp/src/binding.rs:290codex-mcp/src/connection_manager.rs:629
Root cause: Both conversion functions silently discard serialization failures:
meta: result.meta.and_then(|meta| serde_json::to_value(meta).ok()),
If serde_json::to_value(meta) fails (e.g., due to non-UTF-8 strings, unsupported types, or circular references), the meta field is set to None. Downstream consumers that rely on meta for sandbox policy decisions would see no meta and fall back to defaults.
Additionally, the content serialization has a similar issue:
serde_json::to_value(content).unwrap_or_else(|_| JsonValue::String("<content>".to_string()))
If an RMCP content item cannot be serialized, it is silently replaced with the literal string "<content>". The model would see a meaningless placeholder instead of an error message.
Impact:
- Sandbox state meta could be lost, causing the sandbox policy to fall back to a more permissive default
- Tool output content could be replaced with
<content>placeholder, confusing the model
What steps can reproduce the bug?
- Configure an MCP server that returns tool results with non-serializable meta (e.g., containing non-UTF-8 bytes or unsupported types)
- Call the tool from Codex
- The meta is silently dropped and sandbox policy may fall back to default
What is the expected behavior?
The serialization failure should be logged at warn! level so it's observable, and the meta should be preserved if possible (e.g., by converting to a string representation).
Suggested fix
meta: result.meta.and_then(|meta| {
match serde_json::to_value(meta) {
Ok(value) => Some(value),
Err(err) => {
tracing::warn!("failed to serialize MCP tool meta: {err}");
None
}
}
}),
Related
- #33717 — Deferred MCP tool calls drop structuredContent/_meta (similar issue in deferred path)
- #29539 — Windows Computer Use fails: codex/sandbox-state-meta missing sandboxPolicy
Scope
Two call sites in two files. The fix is ~5 lines per call site. No behavioral change for正常 servers — only logging for the failure path.