Skip to content

Commit 04a0539

Browse files
committed
MSCxxxx: M_INCOMPATIBLE_SERVER error code
Specify appropriate error codes for MSC4291 and MSC4311 where it was left as a 5xx.
1 parent 18f4cac commit 04a0539

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# MSCxxxx: `M_INCOMPATIBLE_SERVER` error code
2+
3+
Following [MSC4291](https://github.com/matrix-org/matrix-spec-proposals/pull/4291) and
4+
[MSC4311](https://github.com/matrix-org/matrix-spec-proposals/pull/4311), the Server-Server API
5+
tells sending servers to convert certain federation errors into 5xx errors over the Client-Server
6+
API. [`PUT /_matrix/federation/v2/send_join/{roomId}/{eventId}`](https://spec.matrix.org/v1.19/server-server-api/#put_matrixfederationv2send_joinroomideventid)
7+
and [`PUT /_matrix/federation/v2/invite/{roomId}/{eventId}`](https://spec.matrix.org/v1.19/server-server-api/#put_matrixfederationv2inviteroomideventid)
8+
both say of their `400` response:
9+
10+
> If `M_MISSING_PARAM` or `M_INVALID_PARAM` is returned and the request is associated
11+
> with a Client-Server API request, the Client-Server API request SHOULD fail
12+
> with a 5xx error rather than being passed through.
13+
14+
These rejections occur when the events in the request fail the validation introduced by those MSCs,
15+
for example when an invite lacks a full-PDU `m.room.create` event in its stripped state. The
16+
rationale for a 5xx is that there is nothing the client can do differently to make the request
17+
succeed.
18+
19+
This translation has three problems:
20+
21+
1. No specific status code or `errcode` is given, so implementations will diverge. Clients therefore
22+
cannot give a more helpful error message.
23+
24+
2. Many clients and client SDKs automatically retry requests which fail with a 5xx status code.
25+
However, the failures in the MSCs are not transient as the two servers will remain incompatible
26+
until one of them is updated, which will not happen within any retry window.
27+
28+
3. There is no good 5xx error code to use. 500 response rates are often monitored and assumed to
29+
mean something has gone wrong and needs fixing. 502/503 response are often interpreted by reverse
30+
proxies and load balancers as the backend being down, and stop sending traffic to it. The other
31+
defined 5xx errors don't strictly match, and are rarely used.
32+
33+
This proposal replaces the 5xx translation with a `400` response carrying a new standard error code,
34+
`M_INCOMPATIBLE_SERVER`, meaning the request failed because the local server and a remote server it
35+
needed to communicate with are incompatible with each other.
36+
37+
## Proposal
38+
39+
A new standard error code is added to the Client-Server API:
40+
41+
* `M_INCOMPATIBLE_SERVER`: The request could not be completed because it required communicating with
42+
a remote server which is incompatible with the local server. This is returned with a `400` HTTP
43+
status code.
44+
45+
Clients SHOULD NOT automatically retry a request which failed with `M_INCOMPATIBLE_SERVER` and
46+
SHOULD surface the failure to the user. Servers MAY use the human-readable `error` field to describe
47+
the incompatibility.
48+
49+
Proposals SHOULD strive to maintain backwards compatibility where feasible, rather than use
50+
`M_INCOMPATIBLE_SERVER`.
51+
52+
The paragraph quoted above is replaced, on both the `/send_join` and `/invite` endpoints, with the
53+
following:
54+
55+
> If `M_MISSING_PARAM` or `M_INVALID_PARAM` is returned and the request is associated with a
56+
> Client-Server API request, the Client-Server API request SHOULD fail with a
57+
> `400 M_INCOMPATIBLE_SERVER` standard Matrix error rather than the federation error being passed
58+
> through. There is nothing the client can materially do differently to make the request succeed,
59+
> so the error is shown to the user rather than retried.
60+
61+
For example, a client calling [`POST /_matrix/client/v3/rooms/{roomId}/invite`](https://spec.matrix.org/v1.19/client-server-api/#post_matrixclientv3roomsroomidinvite)
62+
where the invited user's server rejects the federation invite would receive:
63+
64+
```json
65+
{
66+
"errcode": "M_INCOMPATIBLE_SERVER",
67+
"error": "example.org rejected the invite because the two servers are incompatible. One of them may need updating."
68+
}
69+
```
70+
71+
Note that the message does not say which server is at fault. On receiving the federation error, the
72+
sending server cannot know which of the two implementations is outdated.
73+
74+
While the MSC4291 and MSC4311 validation failures are the motivating cases, the error code is
75+
defined generically. Other endpoints and future proposals MAY use `M_INCOMPATIBLE_SERVER` wherever
76+
a request fails because a remote server could not interoperate with the local server, rather than
77+
because of a client error or a fault within the local server itself.
78+
79+
## Potential issues
80+
81+
* Strictly speaking, `400` is the wrong class for this failure. The client's request was well-formed
82+
and the fault lies between the two servers. In practice, however, Matrix (and the lot of the web)
83+
treats 4xx responses as permanent failures and 5xx responses as potentially transient ones. The
84+
strict interpretation of the status ranges offers no third option for a final error that is
85+
no-one's fault (which is the case here). Matrix already returns `400` for failures outside the
86+
client's control, such as
87+
[`M_INCOMPATIBLE_ROOM_VERSION`](https://spec.matrix.org/v1.19/client-server-api/#other-error-codes).
88+
89+
* The receiving server may return `M_MISSING_PARAM` or `M_INVALID_PARAM` because of a bug rather
90+
than version skew. The sending server cannot tell the difference, and does not need to. Either
91+
way the two implementations failed to interoperate, and retrying will not help.
92+
93+
* This proposal is backwards compatible as the current text is only a SHOULD and does not specify
94+
the response body. Given the underspecified nature of the existing text, no client can be relying
95+
on the current behaviour anyway.
96+
97+
## Alternatives
98+
99+
We could keep the 5xx translation but specify it fully, e.g. as `502 M_INCOMPATIBLE_SERVER`. In
100+
strict HTTP terms `502 Bad Gateway` is the closest fit, since the local server is acting as a
101+
gateway to a remote server which returned an unusable response. However, using a 502 here goes
102+
against the common assumptions made by clients and proxies about such errors.
103+
104+
## Security considerations
105+
106+
None foreseen.
107+
108+
## Unstable prefix
109+
110+
None needed.
111+
112+
## Dependencies
113+
114+
None.

0 commit comments

Comments
 (0)