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.

[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 9, 2024
1 parent d67dd88 commit 46dc871
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 206 deletions.
173 changes: 173 additions & 0 deletions content/appendices.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,179 @@ 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_UNKNOWN_TOKEN`
The access or refresh token specified was not recognised.

An additional response parameter, `soft_logout`, might be present on the
response for 401 HTTP status codes. See [the soft logout
section](#soft-logout) for more information.

`M_MISSING_TOKEN`
No access token was specified for the request.

`M_USER_LOCKED`
The account has been [locked](#account-locking) and cannot be used 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.

`M_USER_DEACTIVATED`
The user ID associated with the request has been deactivated. Typically
for endpoints that prove authentication, such as `/login`.

`M_USER_IN_USE`
Encountered when trying to register a user ID which has been taken.

`M_INVALID_USERNAME`
Encountered when trying to register a user ID which is not valid.

`M_ROOM_IN_USE`
Sent when the room alias given to the `createRoom` API is already in
use.

`M_INVALID_ROOM_STATE`
Sent when the initial state given to the `createRoom` API is invalid.

`M_THREEPID_IN_USE`
Sent when a threepid given to an API cannot be used because the same
threepid is already in use.

`M_THREEPID_NOT_FOUND`
Sent when a threepid given to an API cannot be used because no record
matching the threepid was found.

`M_THREEPID_AUTH_FAILED`
Authentication could not be performed on the third-party identifier.

`M_THREEPID_DENIED`
The server does not permit this third-party identifier. This may happen
if the server only permits, for example, email addresses from a
particular domain.

`M_SERVER_NOT_TRUSTED`
The client's request used a third-party server, e.g. identity server,
that this server does not trust.

`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.

`M_BAD_STATE`
The state change requested cannot be performed, such as attempting to
unban a user who is not banned.

`M_GUEST_ACCESS_FORBIDDEN`
The room or resource does not permit guests to access it.

`M_CAPTCHA_NEEDED`
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 account data, 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.

## 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. Similiarly, 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
172 changes: 2 additions & 170 deletions content/client-server-api/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,176 +50,8 @@ 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.

#### 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_UNKNOWN_TOKEN`
The access or refresh token specified was not recognised.

An additional response parameter, `soft_logout`, might be present on the
response for 401 HTTP status codes. See [the soft logout
section](#soft-logout) for more information.

`M_MISSING_TOKEN`
No access token was specified for the request.

`M_USER_LOCKED`
The account has been [locked](#account-locking) and cannot be used 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.

`M_USER_DEACTIVATED`
The user ID associated with the request has been deactivated. Typically
for endpoints that prove authentication, such as `/login`.

`M_USER_IN_USE`
Encountered when trying to register a user ID which has been taken.

`M_INVALID_USERNAME`
Encountered when trying to register a user ID which is not valid.

`M_ROOM_IN_USE`
Sent when the room alias given to the `createRoom` API is already in
use.

`M_INVALID_ROOM_STATE`
Sent when the initial state given to the `createRoom` API is invalid.

`M_THREEPID_IN_USE`
Sent when a threepid given to an API cannot be used because the same
threepid is already in use.

`M_THREEPID_NOT_FOUND`
Sent when a threepid given to an API cannot be used because no record
matching the threepid was found.

`M_THREEPID_AUTH_FAILED`
Authentication could not be performed on the third-party identifier.

`M_THREEPID_DENIED`
The server does not permit this third-party identifier. This may happen
if the server only permits, for example, email addresses from a
particular domain.

`M_SERVER_NOT_TRUSTED`
The client's request used a third-party server, e.g. identity server,
that this server does not trust.

`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.

`M_BAD_STATE`
The state change requested cannot be performed, such as attempting to
unban a user who is not banned.

`M_GUEST_ACCESS_FORBIDDEN`
The room or resource does not permit guests to access it.

`M_CAPTCHA_NEEDED`
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 account data, 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.
All client-server API endpoints MUST return error responses conforming to the
[standard error response](/appendices#standard-error-response) schema.

#### Rate limiting

Expand Down
Loading

0 comments on commit 46dc871

Please sign in to comment.