Skip to content

Invalid UTF-8 in a request string returns 500 instead of 400 (Streamable HTTP) #1983

Closed as not planned

Description

@skulkarniaugeomarketing

Description
If a POST body contains a JSON string value that is not valid UTF-8, the Streamable HTTP
handler returns 500 Internal Server Error. The JSON reader accepts the bytes, but
ValidateProtocolVersionEnvelope later calls JsonValue.TryGetValue(out string), which throws
InvalidOperationException: Cannot transcode invalid UTF-8 JSON text to UTF-16 string.
HandlePostRequestAsync only catches JsonException, so the exception escapes.

This is related to #788 and was first noted by @rajashree23 in a comment on #1709. That PR
does not cover it. I found two paths:

  1. _meta/io.modelcontextprotocol/protocolVersion on a 2026-07-28 request
    (TryGetProtocolVersionMeta).
  2. params.protocolVersion on an initialize request with an MCP-Protocol-Version header.

Steps to reproduce
POST a body where the protocol version string contains the byte 0xFF, for example
..."protocolVersion":"2025-11-25<0xFF>"..., with header MCP-Protocol-Version: 2025-11-25.

Expected
400 Bad Request with a JSON-RPC error that echoes the request id, consistent with the
other validation failures in this handler.

Actual
500 Internal Server Error. Reproduced on current main (deb6afa) and in v2.3.0.

Proposed fix
Treat the transcoding failure as a client error: catch it around the body validation in
HandlePostRequestAsync and return 400 with a JSON-RPC error. I have two failing tests
in HttpHeaderConformanceTests that reproduce both paths.

Question for maintainers: should the error code be InvalidRequest (-32600), to match the
existing JsonException handling, or ParseError (-32700), because invalid UTF-8 is not
valid JSON text under RFC 8259?

I would like to work on this if that is OK.

Activity

  1. skulkarniaugeomarketing commented on Nov 1, 2026

    @skulkarniaugeomarketing
    Author

    Posted from the wrong account by mistake. Closing as a duplicate of #1984, which has the same content.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions