codex - 💡(How to fix) Fix MCP transport silently swallows non-2xx HTTP errors as JSON-RPC deserialization failures [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openai/codex#20513Fetched 2026-05-01 05:42:17
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
1
Participants
Timeline (top)
labeled ×3cross-referenced ×1unlabeled ×1

Error Message

Transport[rmcp::transport::worker::WorkerTransport< rmcp::transport::streamable_http_client::StreamableHttpClientWorker< codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter

] error: Deserialize error: data did not match any variant of untagged enum JsonRpcMessage

Root Cause

The root cause is in codex-rs/rmcp-client/src/http_client_adapter.rs in the post_message method. After handling 401, 404, 202, and 204 explicitly, the code branches directly on Content-Type without a general non-2xx guard:

Code Example

Transport[rmcp::transport::worker::WorkerTransport<
   rmcp::transport::streamable_http_client::StreamableHttpClientWorker<
      codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter
   >
>] error: Deserialize error: data did not match any variant of untagged enum JsonRpcMessage

---

HTTP/1.1 403 Forbidden
Content-Type: application/json

{"error":"insufficient_scope","error_description":"Insufficient scope"}

---

MCP tool call failed: HTTP 403 Forbidden - {"error":"insufficient_scope","error_description":"Insufficient scope"}

---

if !status.is_success() {
   let body = collect_body(&mut body_stream).await?;
   return Err(StreamableHttpError::UnexpectedServerResponse(
      format!("HTTP {}: {}", status, String::from_utf8_lossy(&body)),
   ));
}
RAW_BUFFERClick to expand / collapse

What version of Codex CLI is running?

0.125.0

What subscription do you have?

Enterprise

Which model were you using?

gpt-5.5

What platform is your computer?

Darwin 25.4.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

No response

What issue are you seeing?

When an MCP server returns a non-2xx HTTP response with Content-Type: application/json (e.g., a 403 Forbidden for insufficient OAuth scope), Codex reports a confusing deserialization error instead of the actual HTTP error:

Transport[rmcp::transport::worker::WorkerTransport<
   rmcp::transport::streamable_http_client::StreamableHttpClientWorker<
      codex_rmcp_client::http_client_adapter::StreamableHttpClientAdapter
   >
>] error: Deserialize error: data did not match any variant of untagged enum JsonRpcMessage

The actual server response was:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{"error":"insufficient_scope","error_description":"Insufficient scope"}

What steps can reproduce the bug?

  1. Configure an MCP server that returns 403 with a JSON body for unauthorized tool calls (e.g., an OAuth-protected server where the token lacks the required scope).
  2. Invoke any tool via Codex that triggers the 403.
  3. Observe that the error message mentions a JSON-RPC deserialization failure rather than the HTTP 403.

What is the expected behavior?

Codex should detect the non-2xx status code before attempting to deserialize the body as a JsonRpcMessage, and surface a clear error like:

MCP tool call failed: HTTP 403 Forbidden - {"error":"insufficient_scope","error_description":"Insufficient scope"}

Additional information

The root cause is in codex-rs/rmcp-client/src/http_client_adapter.rs in the post_message method. After handling 401, 404, 202, and 204 explicitly, the code branches directly on Content-Type without a general non-2xx guard:

https://github.com/openai/codex/blob/8426edf71e4a5b754467749ce16090515e2c13c9/codex-rs/rmcp-client/src/http_client_adapter.rs#L158-L163 (A 403 with Content-Type: application/json falls into this branch.)

The fix would be to add a non-2xx guard before the content-type branch - the same pattern already used in get_stream in the same file:

if !status.is_success() {
   let body = collect_body(&mut body_stream).await?;
   return Err(StreamableHttpError::UnexpectedServerResponse(
      format!("HTTP {}: {}", status, String::from_utf8_lossy(&body)),
   ));
}

extent analysis

TL;DR

Add a non-2xx guard before the content-type branch in the post_message method to handle HTTP errors correctly.

Guidance

  • Review the post_message method in http_client_adapter.rs to understand the current handling of HTTP responses.
  • Add a check for non-2xx status codes before attempting to deserialize the response body as JSON.
  • Use the existing pattern in get_stream as a reference for implementing the non-2xx guard.
  • Verify that the fix handles cases where the server returns a non-2xx response with a JSON body.

Example

if !status.is_success() {
   let body = collect_body(&mut body_stream).await?;
   return Err(StreamableHttpError::UnexpectedServerResponse(
      format!("HTTP {}: {}", status, String::from_utf8_lossy(&body)),
   ));
}

This code snippet demonstrates the non-2xx guard pattern used in get_stream, which can be applied to post_message to fix the issue.

Notes

The fix requires modifying the codex-rs/rmcp-client code, specifically the post_message method in http_client_adapter.rs. The provided code snippet is a reference implementation and may need to be adapted to fit the exact requirements of the post_message method.

Recommendation

Apply the workaround by adding a non-2xx guard to the post_message method, as this will correctly handle HTTP errors and provide a clear error message to the user.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix MCP transport silently swallows non-2xx HTTP errors as JSON-RPC deserialization failures [1 participants]