Stop answering cancelled requests (#3188)

This commit is contained in:
Max 2026-07-27 23:26:00 +01:00 • committed by GitHub
commit 923341c98a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -537,14 +537,16 @@ REQUIREMENTS: dict[str, Requirement] = {
source=f"{SPEC_BASE_URL}/basic/utilities/cancellation#behavior-requirements",
behavior=(
"A cancellation notification for an in-flight request stops the server-side handler, and the "
"receiver does not send a response for the cancelled request."
"receiver does not send a response for the cancelled request - no result and no error."
),
divergence=Divergence(
note=(
"The spec says receivers of a cancellation SHOULD NOT send a response for the cancelled "
"request; both seats send an error response (code 0, 'Request cancelled') instead — the "
"server for cancelled client requests, and the client for cancelled server-initiated "
"requests — which is what unblocks the sender's pending call."
"The 2025-era streamable HTTP transport still answers a cancelled request, with a "
"REQUEST_CANCELLED (-32800) error - deliberate and era-scoped: that wire ends a request's "
"stream only with a response for its id, so silence would leave the POST (and any "
"resuming client's replay) open. Every other transport sends nothing, and the "
"2026-07-28 MUST NOT applies only there. Retires with the legacy transport; see "
"transport:streamable-http:cancelled-request-terminated."
),
),
arm_exclusions=(
@ -2559,6 +2561,22 @@ REQUIREMENTS: dict[str, Requirement] = {
transports=("streamable-http",),
note="Only observable over streamable HTTP: JSON-response mode is an HTTP framing option.",
),
"transport:streamable-http:cancelled-request-terminated": Requirement(
source="sdk",
behavior=(
"A request cancelled through notifications/cancelled is terminated with a REQUEST_CANCELLED "
"(-32800) error response, completing its POST - the JSON body in JSON-response mode, the "
"final event of its stream in SSE mode."
),
transports=("streamable-http",),
note=(
"An SDK choice, not spec-mandated (the spec-side gap is the Divergence on "
"protocol:cancel:in-flight): this era's wire ends a request's stream only with a response "
"for its id, and stores it so a resuming client's replay terminates too. The terminator is "
"written through the same ordered channel as the request's other messages, so it cannot "
"overtake anything already queued for the request."
),
),
"transport:streamable-http:stateless": Requirement(
source=f"{SPEC_BASE_URL}/basic/transports#streamable-http",
behavior=(