Skip to content

Commit

Permalink
move standard error schema to appendices and share between all APIs
Browse files Browse the repository at this point in the history
I asked about this on matrix, and tulir confirmed[1] that the error
schema was intended to be shared between all APIs. I would like the
shared schema to be explicit in the spec text so that ruma can move to
using the same error type for client-server and server-server endpoints.
This would simplify error handling in server implementations.

Error codes that are used in more than one API were moved to the
appendices, while error codes specific to only one API were left there.
Since the docs on which error codes are actually used by which endpoints
aren't very complemete, I determined this by looking at the synapse
source code.

[1]: https://matrix.to/#/#matrix-spec-discussion:neko.dev/$Y2yTCeR_AeW6g_4jViFbx4gTE_AwF0RN7yrHJ25F5Q8

Signed-off-by: Olivia Lee <[email protected]>
  • Loading branch information
olivia-fl committed Dec 13, 2024
1 parent af6e8a2 commit 9bbb9c5
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 153 deletions.
1 change: 1 addition & 0 deletions changelogs/appendices/newsfragments/2026.clarification
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Move standard error response schema from client-server API to appendices.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Specify that error responses must conform to the standard error response schema.
1 change: 1 addition & 0 deletions changelogs/client_server/newsfragments/2026.clarification
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Move standard error response schema from client-server API to appendices.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Reference standard error response schema from appendices instead of embedding it.
1 change: 1 addition & 0 deletions changelogs/push_gateway/newsfragments/2026.clarification
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Specify that error responses must conform to the standard error response schema.
130 changes: 130 additions & 0 deletions content/appendices.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,136 @@ weight: 70
type: docs
---

## Standard error response

Any errors which occur at the Matrix API level MUST return a "standard
error response". This is a JSON object which looks like:

```json
{
"errcode": "<error code>",
"error": "<error message>"
}
```

The `error` string will be a human-readable error message, usually a
sentence explaining what went wrong.

The `errcode` string will be a unique string which can be used to handle an
error message e.g. `M_FORBIDDEN`. Error codes should have their namespace
first in ALL CAPS, followed by a single `_`. For example, if there was a custom
namespace `com.mydomain.here`, and a `FORBIDDEN` code, the error code should
look like `COM.MYDOMAIN.HERE_FORBIDDEN`. Error codes defined by this
specification should start with `M_`.

Some `errcode`s define additional keys which should be present in the error
response object, but the keys `error` and `errcode` MUST always be present.

Errors are generally best expressed by their error code rather than the
HTTP status code returned. When encountering the error code `M_UNKNOWN`,
clients should prefer the HTTP status code as a more reliable reference
for what the issue was. For example, if the client receives an error
code of `M_NOT_FOUND` but the request gave a 400 Bad Request status
code, the client should treat the error as if the resource was not
found. However, if the client were to receive an error code of
`M_UNKNOWN` with a 400 Bad Request, the client should assume that the
request being made was invalid.

#### Common error codes

These error codes can be returned by any API endpoint:

`M_FORBIDDEN`
Forbidden access, e.g. joining a room without permission, failed login.

`M_BAD_JSON`
Request contained valid JSON, but it was malformed in some way, e.g.
missing required keys, invalid values for keys.

`M_NOT_JSON`
Request did not contain valid JSON.

`M_NOT_FOUND`
No resource was found for this request.

`M_LIMIT_EXCEEDED`
Too many requests have been sent in a short period of time. Wait a while
then try again. See [Rate limiting](#rate-limiting).

`M_UNRECOGNIZED`
The server did not understand the request. This is expected to be returned with
a 404 HTTP status code if the endpoint is not implemented or a 405 HTTP status
code if the endpoint is implemented, but the incorrect HTTP method is used.

`M_UNKNOWN`
An unknown error has occurred.

#### Other error codes

The following error codes are specific to certain endpoints.

<!-- TODO: move them to the endpoints that return them -->

`M_UNAUTHORIZED`
The request was not correctly authorized. Usually due to login failures.

`M_MISSING_PARAM`
A required parameter was missing from the request.

`M_INVALID_PARAM`
A parameter that was specified has the wrong value. For example, the
server expected an integer and instead received a string.

`M_TOO_LARGE`
The request or entity was too large.

`M_EXCLUSIVE`
The resource being requested is reserved by an application service, or
the application service making the request has not created the resource.

`M_RESOURCE_LIMIT_EXCEEDED`
The request cannot be completed because the homeserver has reached a
resource limit imposed on it. For example, a homeserver held in a shared
hosting environment may reach a resource limit if it starts using too
much memory or disk space. The error MUST have an `admin_contact` field
to provide the user receiving the error a place to reach out to.
Typically, this error will appear on routes which attempt to modify
state (e.g.: sending messages, account data, etc) and not routes which
only read state (e.g.: [`/client/sync`](/client-server-api/#get_matrixclientv3sync),
[`/client/user/{userId}/account_data/{type}`](/client-server-api/#get_matrixclientv3useruseridaccount_datatype), etc).

`M_UNSUPPORTED_ROOM_VERSION`
The client's request to create a room used a room version that the
server does not support.

`M_INCOMPATIBLE_ROOM_VERSION`
The client attempted to join a room that has a version the server does
not support. Inspect the `room_version` property of the error response
for the room's version.

#### Rate limiting

Homeservers SHOULD implement rate limiting to reduce the risk of being
overloaded. If a request is refused due to rate limiting, it should
return a standard error response of the form:

```json
{
"errcode": "M_LIMIT_EXCEEDED",
"error": "string",
"retry_after_ms": integer (optional, deprecated)
}
```

Homeservers SHOULD include a [`Retry-After`](https://www.rfc-editor.org/rfc/rfc9110#field.retry-after)
header for any response with a 429 status code.

The `retry_after_ms` property MAY be included to tell the client how long
they have to wait in milliseconds before they can try again. This property is
deprecated, in favour of the `Retry-After` header.

{{% changed-in v="1.10" %}}: `retry_after_ms` property deprecated in favour of `Retry-After` header.

## Unpadded Base64

*Unpadded* Base64 refers to 'standard' Base64 encoding as defined in
Expand Down
10 changes: 10 additions & 0 deletions content/application-service-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ Application Service API (AS API) defines a standard API to allow such
extensible functionality to be implemented irrespective of the
underlying homeserver implementation.

## API standards

### Standard error response

All homeserver -> application service API endpoints MUST return error responses
conforming to the [standard error response](/appendices#standard-error-response)
schema. Similarly, all application service client-server API extension
endpoints MUST return error responses conforming to the standard error response
schema.

## Application Services

Application services are passive and can only observe events from the
Expand Down
123 changes: 6 additions & 117 deletions content/client-server-api/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,45 +50,13 @@ requirements for server responses.

### Standard error response

Any errors which occur at the Matrix API level MUST return a "standard
error response". This is a JSON object which looks like:

```json
{
"errcode": "<error code>",
"error": "<error message>"
}
```

The `error` string will be a human-readable error message, usually a
sentence explaining what went wrong.

The `errcode` string will be a unique string which can be used to handle an
error message e.g. `M_FORBIDDEN`. Error codes should have their namespace
first in ALL CAPS, followed by a single `_`. For example, if there was a custom
namespace `com.mydomain.here`, and a `FORBIDDEN` code, the error code should
look like `COM.MYDOMAIN.HERE_FORBIDDEN`. Error codes defined by this
specification should start with `M_`.

Some `errcode`s define additional keys which should be present in the error
response object, but the keys `error` and `errcode` MUST always be present.

Errors are generally best expressed by their error code rather than the
HTTP status code returned. When encountering the error code `M_UNKNOWN`,
clients should prefer the HTTP status code as a more reliable reference
for what the issue was. For example, if the client receives an error
code of `M_NOT_FOUND` but the request gave a 400 Bad Request status
code, the client should treat the error as if the resource was not
found. However, if the client were to receive an error code of
`M_UNKNOWN` with a 400 Bad Request, the client should assume that the
request being made was invalid.
All client-server API endpoints MUST return error responses conforming to the
[standard error response](/appendices#standard-error-response) schema.

#### Common error codes

These error codes can be returned by any API endpoint:

`M_FORBIDDEN`
Forbidden access, e.g. joining a room without permission, failed login.
In addition to the standard error codes listed in the appendix, the following
standard error codes can be returned by any client-server API endpoint:

`M_UNKNOWN_TOKEN`
The access or refresh token specified was not recognised.
Expand All @@ -107,36 +75,10 @@ The account has been [locked](#account-locking) and cannot be used at this time.
The account has been [suspended](#account-suspension) and can only be used for
limited actions at this time.

`M_BAD_JSON`
Request contained valid JSON, but it was malformed in some way, e.g.
missing required keys, invalid values for keys.

`M_NOT_JSON`
Request did not contain valid JSON.

`M_NOT_FOUND`
No resource was found for this request.

`M_LIMIT_EXCEEDED`
Too many requests have been sent in a short period of time. Wait a while
then try again. See [Rate limiting](#rate-limiting).

`M_UNRECOGNIZED`
The server did not understand the request. This is expected to be returned with
a 404 HTTP status code if the endpoint is not implemented or a 405 HTTP status
code if the endpoint is implemented, but the incorrect HTTP method is used.

`M_UNKNOWN`
An unknown error has occurred.

#### Other error codes

The following error codes are specific to certain endpoints.

<!-- TODO: move them to the endpoints that return them -->

`M_UNAUTHORIZED`
The request was not correctly authorized. Usually due to login failures.
In addition to the standard error codes listed in the appendix, the following
standard error codes can be returned by specific client-server API endpoints:

`M_USER_DEACTIVATED`
The user ID associated with the request has been deactivated. Typically
Expand Down Expand Up @@ -179,11 +121,6 @@ that this server does not trust.
The client's request to create a room used a room version that the
server does not support.

`M_INCOMPATIBLE_ROOM_VERSION`
The client attempted to join a room that has a version the server does
not support. Inspect the `room_version` property of the error response
for the room's version.

`M_BAD_STATE`
The state change requested cannot be performed, such as attempting to
unban a user who is not banned.
Expand All @@ -197,61 +134,13 @@ A Captcha is required to complete the request.
`M_CAPTCHA_INVALID`
The Captcha provided did not match what was expected.

`M_MISSING_PARAM`
A required parameter was missing from the request.

`M_INVALID_PARAM`
A parameter that was specified has the wrong value. For example, the
server expected an integer and instead received a string.

`M_TOO_LARGE`
The request or entity was too large.

`M_EXCLUSIVE`
The resource being requested is reserved by an application service, or
the application service making the request has not created the resource.

`M_RESOURCE_LIMIT_EXCEEDED`
The request cannot be completed because the homeserver has reached a
resource limit imposed on it. For example, a homeserver held in a shared
hosting environment may reach a resource limit if it starts using too
much memory or disk space. The error MUST have an `admin_contact` field
to provide the user receiving the error a place to reach out to.
Typically, this error will appear on routes which attempt to modify
state (e.g.: sending messages, account data, etc) and not routes which
only read state (e.g.: [`/sync`](#get_matrixclientv3sync),
[`/user/{userId}/account_data/{type}`](#get_matrixclientv3useruseridaccount_datatype), etc).

`M_CANNOT_LEAVE_SERVER_NOTICE_ROOM`
The user is unable to reject an invite to join the server notices room.
See the [Server Notices](#server-notices) module for more information.

`M_THREEPID_MEDIUM_NOT_SUPPORTED`
The homeserver does not support adding a third party identifier of the given medium.

#### Rate limiting

Homeservers SHOULD implement rate limiting to reduce the risk of being
overloaded. If a request is refused due to rate limiting, it should
return a standard error response of the form:

```json
{
"errcode": "M_LIMIT_EXCEEDED",
"error": "string",
"retry_after_ms": integer (optional, deprecated)
}
```

Homeservers SHOULD include a [`Retry-After`](https://www.rfc-editor.org/rfc/rfc9110#field.retry-after)
header for any response with a 429 status code.

The `retry_after_ms` property MAY be included to tell the client how long
they have to wait in milliseconds before they can try again. This property is
deprecated, in favour of the `Retry-After` header.

{{% changed-in v="1.10" %}}: `retry_after_ms` property deprecated in favour of `Retry-After` header.

### Transaction identifiers

The client-server API typically uses `HTTP PUT` to submit requests with
Expand Down
40 changes: 4 additions & 36 deletions content/identity-service-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,11 @@ All JSON data, in requests or responses, must be encoded using UTF-8.

### Standard error response

Any errors which occur at the Matrix API level MUST return a "standard
error response". This is a JSON object which looks like:
All identity service API endpoints MUST return error responses conforming to
the [standard error response](/appendices#standard-error-response) schema.

```json
{
"errcode": "<error code>",
"error": "<error message>"
}
```

The `error` string will be a human-readable error message, usually a
sentence explaining what went wrong. The `errcode` string will be a
unique string which can be used to handle an error message e.g.
`M_FORBIDDEN`. There may be additional keys depending on the error, but
the keys `error` and `errcode` MUST always be present.

Some standard error codes are below:

`M_NOT_FOUND`
The resource requested could not be located.
In addition to the standard error codes listed in the appendix, the following
standard error codes are specific to the the identity service API:

`M_MISSING_PARAMS`
The request was missing one or more parameters.
Expand Down Expand Up @@ -104,23 +89,6 @@ The provided third-party address was not valid.
There was an error sending a notification. Typically seen when
attempting to verify ownership of a given third-party address.

`M_UNRECOGNIZED`
The request contained an unrecognised value, such as an unknown token or
medium.

This is also used as the response if a server did not understand the request.
This is expected to be returned with a 404 HTTP status code if the endpoint is
not implemented or a 405 HTTP status code if the endpoint is implemented, but
the incorrect HTTP method is used.

`M_THREEPID_IN_USE`
The third-party identifier is already in use by another user. Typically
this error will have an additional `mxid` property to indicate who owns
the third-party identifier.

`M_UNKNOWN`
An unknown error has occurred.

## Privacy

Identity is a privacy-sensitive issue. While the identity server exists
Expand Down
5 changes: 5 additions & 0 deletions content/push-gateway-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ notification provider (e.g. APNS, GCM).

## API standards

### Standard error response

All push gateway API endpoints MUST return error responses conforming to the
[standard error response](/appendices#standard-error-response) schema.

### Unsupported endpoints

If a request for an unsupported (or unknown) endpoint is received then the server
Expand Down
Loading

0 comments on commit 9bbb9c5

Please sign in to comment.