Skip to main content

ruma_common/api/error/
kind.rs

1use std::str::FromStr;
2
3use as_variant::as_variant;
4use ruma_common::{
5    RoomVersionId,
6    api::error::{HeaderDeserializationError, HeaderSerializationError},
7    http_headers::{http_date_to_system_time, system_time_to_http_date},
8    serde::{JsonObject, StringEnum},
9};
10use web_time::{Duration, SystemTime};
11
12use crate::PrivOwnedStr;
13
14/// An enum for the error kind.
15///
16/// Items may contain additional information.
17#[derive(Clone, Debug, PartialEq, Eq)]
18#[non_exhaustive]
19// Please keep the variants sorted alphabetically.
20pub enum ErrorKind {
21    /// `M_APPSERVICE_LOGIN_UNSUPPORTED`
22    ///
23    /// An application service used the [`m.login.application_service`] type an endpoint from the
24    /// [legacy authentication API] in a way that is not supported by the homeserver, because the
25    /// server only supports the [OAuth 2.0 API].
26    ///
27    /// [`m.login.application_service`]: https://spec.matrix.org/v1.18/application-service-api/#server-admin-style-permissions
28    /// [legacy authentication API]: https://spec.matrix.org/v1.18/client-server-api/#legacy-api
29    /// [OAuth 2.0 API]: https://spec.matrix.org/v1.18/client-server-api/#oauth-20-api
30    AppserviceLoginUnsupported,
31
32    /// `M_BAD_ALIAS`
33    ///
34    /// One or more [room aliases] within the `m.room.canonical_alias` event do not point to the
35    /// room ID for which the state event is to be sent to.
36    ///
37    /// [room aliases]: https://spec.matrix.org/v1.18/client-server-api/#room-aliases
38    BadAlias,
39
40    /// `M_BAD_JSON`
41    ///
42    /// The request contained valid JSON, but it was malformed in some way, e.g. missing required
43    /// keys, invalid values for keys.
44    BadJson,
45
46    /// `M_BAD_STATE`
47    ///
48    /// The state change requested cannot be performed, such as attempting to unban a user who is
49    /// not banned.
50    BadState,
51
52    /// `M_BAD_STATUS`
53    ///
54    /// The application service returned a bad status.
55    BadStatus(BadStatusErrorData),
56
57    /// `M_CANNOT_LEAVE_SERVER_NOTICE_ROOM`
58    ///
59    /// The user is unable to reject an invite to join the [server notices] room.
60    ///
61    /// [server notices]: https://spec.matrix.org/v1.18/client-server-api/#server-notices
62    CannotLeaveServerNoticeRoom,
63
64    /// `M_CANNOT_OVERWRITE_MEDIA`
65    ///
66    /// The `PUT /_matrix/media/*/upload/{serverName}/{mediaId}` endpoint was called with a media ID
67    /// that already has content.
68    CannotOverwriteMedia,
69
70    /// `M_CAPTCHA_INVALID`
71    ///
72    /// The Captcha provided did not match what was expected.
73    CaptchaInvalid,
74
75    /// `M_CAPTCHA_NEEDED`
76    ///
77    /// A Captcha is required to complete the request.
78    CaptchaNeeded,
79
80    /// `M_CONFLICTING_UNSUBSCRIPTION`
81    ///
82    /// Part of [MSC4306]: an automatic thread subscription has been skipped by the server, because
83    /// the user unsubsubscribed after the indicated subscribed-to event.
84    ///
85    /// [MSC4306]: https://github.com/matrix-org/matrix-spec-proposals/pull/4306
86    #[cfg(feature = "unstable-msc4306")]
87    ConflictingUnsubscription,
88
89    /// `M_CONNECTION_FAILED`
90    ///
91    /// The connection to the application service failed.
92    ConnectionFailed,
93
94    /// `M_CONNECTION_TIMEOUT`
95    ///
96    /// The connection to the application service timed out.
97    ConnectionTimeout,
98
99    /// `M_DUPLICATE_ANNOTATION`
100    ///
101    /// The request is an attempt to send a [duplicate annotation].
102    ///
103    /// [duplicate annotation]: https://spec.matrix.org/v1.18/client-server-api/#avoiding-duplicate-annotations
104    DuplicateAnnotation,
105
106    /// `M_EXCLUSIVE`
107    ///
108    /// The resource being requested is reserved by an application service, or the application
109    /// service making the request has not created the resource.
110    Exclusive,
111
112    /// `M_FORBIDDEN`
113    ///
114    /// Forbidden access, e.g. joining a room without permission, failed login.
115    Forbidden,
116
117    /// `M_GUEST_ACCESS_FORBIDDEN`
118    ///
119    /// The room or resource does not permit [guests] to access it.
120    ///
121    /// [guests]: https://spec.matrix.org/v1.18/client-server-api/#guest-access
122    GuestAccessForbidden,
123
124    /// `M_INCOMPATIBLE_ROOM_VERSION`
125    ///
126    /// The client attempted to join a room that has a version the server does not support.
127    IncompatibleRoomVersion(IncompatibleRoomVersionErrorData),
128
129    /// `M_INVALID_PARAM`
130    ///
131    /// A parameter that was specified has the wrong value. For example, the server expected an
132    /// integer and instead received a string.
133    InvalidParam,
134
135    /// `M_INVALID_ROOM_STATE`
136    ///
137    /// The initial state implied by the parameters to the `POST /_matrix/client/*/createRoom`
138    /// request is invalid, e.g. the user's `power_level` is set below that necessary to set the
139    /// room name.
140    InvalidRoomState,
141
142    /// `M_INVALID_USERNAME`
143    ///
144    /// The desired user name is not valid.
145    InvalidUsername,
146
147    /// `M_INVITE_BLOCKED`
148    ///
149    /// The invite was interdicted by moderation tools or configured access controls without having
150    /// been witnessed by the invitee.
151    InviteBlocked,
152
153    /// `M_LIMIT_EXCEEDED`
154    ///
155    /// The request has been refused due to [rate limiting]: too many requests have been sent in a
156    /// short period of time.
157    ///
158    /// [rate limiting]: https://spec.matrix.org/v1.18/client-server-api/#rate-limiting
159    LimitExceeded(LimitExceededErrorData),
160
161    /// `M_MISSING_PARAM`
162    ///
163    /// A required parameter was missing from the request.
164    MissingParam,
165
166    /// `M_MISSING_TOKEN`
167    ///
168    /// No [access token] was specified for the request, but one is required.
169    ///
170    /// [access token]: https://spec.matrix.org/v1.18/client-server-api/#client-authentication
171    MissingToken,
172
173    /// `M_NOT_FOUND`
174    ///
175    /// No resource was found for this request.
176    NotFound,
177
178    /// `M_NOT_IN_THREAD`
179    ///
180    /// Part of [MSC4306]: an automatic thread subscription was set to an event ID that isn't part
181    /// of the subscribed-to thread.
182    ///
183    /// [MSC4306]: https://github.com/matrix-org/matrix-spec-proposals/pull/4306
184    #[cfg(feature = "unstable-msc4306")]
185    NotInThread,
186
187    /// `M_NOT_JSON`
188    ///
189    /// The request did not contain valid JSON.
190    NotJson,
191
192    /// `M_NOT_YET_UPLOADED`
193    ///
194    /// An `mxc:` URI generated with the `POST /_matrix/media/*/create` endpoint was used and the
195    /// content is not yet available.
196    NotYetUploaded,
197
198    /// `M_RESOURCE_LIMIT_EXCEEDED`
199    ///
200    /// The request cannot be completed because the homeserver has reached a resource limit imposed
201    /// on it. For example, a homeserver held in a shared hosting environment may reach a resource
202    /// limit if it starts using too much memory or disk space.
203    ResourceLimitExceeded(ResourceLimitExceededErrorData),
204
205    /// `M_ROOM_IN_USE`
206    ///
207    /// The [room alias] specified in the `POST /_matrix/client/*/createRoom` request is already
208    /// taken.
209    ///
210    /// [room alias]: https://spec.matrix.org/v1.18/client-server-api/#room-aliases
211    RoomInUse,
212
213    /// `M_SERVER_NOT_TRUSTED`
214    ///
215    /// The client's request used a third-party server, e.g. identity server, that this server does
216    /// not trust.
217    ServerNotTrusted,
218
219    /// `M_THREEPID_AUTH_FAILED`
220    ///
221    /// Authentication could not be performed on the [third-party identifier].
222    ///
223    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
224    ThreepidAuthFailed,
225
226    /// `M_THREEPID_DENIED`
227    ///
228    /// The server does not permit this [third-party identifier]. This may happen if the server
229    /// only permits, for example, email addresses from a particular domain.
230    ///
231    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
232    ThreepidDenied,
233
234    /// `M_THREEPID_IN_USE`
235    ///
236    /// The [third-party identifier] is already in use by another user.
237    ///
238    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
239    ThreepidInUse,
240
241    /// `M_THREEPID_MEDIUM_NOT_SUPPORTED`
242    ///
243    /// The homeserver does not support adding a [third-party identifier] of the given medium.
244    ///
245    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
246    ThreepidMediumNotSupported,
247
248    /// `M_THREEPID_NOT_FOUND`
249    ///
250    /// No account matching the given [third-party identifier] could be found.
251    ///
252    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
253    ThreepidNotFound,
254
255    /// `M_TOKEN_INCORRECT`
256    ///
257    /// The token that the user entered to validate the session is incorrect.
258    TokenIncorrect,
259
260    /// `M_TOO_LARGE`
261    ///
262    /// The request or entity was too large.
263    TooLarge,
264
265    /// `M_UNABLE_TO_AUTHORISE_JOIN`
266    ///
267    /// The room is [restricted] and none of the conditions can be validated by the homeserver.
268    /// This can happen if the homeserver does not know about any of the rooms listed as
269    /// conditions, for example.
270    ///
271    /// [restricted]: https://spec.matrix.org/v1.18/client-server-api/#restricted-rooms
272    UnableToAuthorizeJoin,
273
274    /// `M_UNABLE_TO_GRANT_JOIN`
275    ///
276    /// A different server should be attempted for the join. This is typically because the resident
277    /// server can see that the joining user satisfies one or more conditions, such as in the case
278    /// of [restricted rooms], but the resident server would be unable to meet the authorization
279    /// rules.
280    ///
281    /// [restricted rooms]: https://spec.matrix.org/v1.18/client-server-api/#restricted-rooms
282    UnableToGrantJoin,
283
284    /// `M_UNACTIONABLE`
285    ///
286    /// The server does not want to handle the [federated report].
287    ///
288    /// [federated report]: https://github.com/matrix-org/matrix-spec-proposals/pull/3843
289    #[cfg(feature = "unstable-msc3843")]
290    Unactionable,
291
292    /// `M_UNAUTHORIZED`
293    ///
294    /// The request was not correctly authorized. Usually due to login failures.
295    Unauthorized,
296
297    /// `M_UNKNOWN`
298    ///
299    /// An unknown error has occurred.
300    Unknown,
301
302    /// `M_UNKNOWN_POS`
303    ///
304    /// The sliding sync ([MSC4186]) connection was expired by the server.
305    ///
306    /// [MSC4186]: https://github.com/matrix-org/matrix-spec-proposals/pull/4186
307    #[cfg(feature = "unstable-msc4186")]
308    UnknownPos,
309
310    /// `M_UNKNOWN_TOKEN`
311    ///
312    /// The [access or refresh token] specified was not recognized.
313    ///
314    /// [access or refresh token]: https://spec.matrix.org/v1.18/client-server-api/#client-authentication
315    UnknownToken(UnknownTokenErrorData),
316
317    /// `M_UNRECOGNIZED`
318    ///
319    /// The server did not understand the request.
320    ///
321    /// This is expected to be returned with a 404 HTTP status code if the endpoint is not
322    /// implemented or a 405 HTTP status code if the endpoint is implemented, but the incorrect
323    /// HTTP method is used.
324    Unrecognized,
325
326    /// `M_UNSUPPORTED_ROOM_VERSION`
327    ///
328    /// The request to `POST /_matrix/client/*/createRoom` used a room version that the server does
329    /// not support.
330    UnsupportedRoomVersion,
331
332    /// `M_URL_NOT_SET`
333    ///
334    /// The application service doesn't have a URL configured.
335    UrlNotSet,
336
337    /// `M_USER_DEACTIVATED`
338    ///
339    /// The user ID associated with the request has been deactivated.
340    UserDeactivated,
341
342    /// `M_USER_IN_USE`
343    ///
344    /// The desired user ID is already taken.
345    UserInUse,
346
347    /// `M_USER_LIMIT_EXCEEDED`
348    ///
349    /// The request cannot be completed because the user has exceeded (or the request would cause
350    /// them to exceed) a limit associated with their account. For example, a user may have reached
351    /// their allocated storage quota, reached a maximum number of allowed rooms, devices, or other
352    /// account-scoped resources, or exceeded usage limits for specific features.
353    UserLimitExceeded(UserLimitExceededErrorData),
354
355    /// `M_USER_LOCKED`
356    ///
357    /// The account has been [locked] and cannot be used at this time.
358    ///
359    /// [locked]: https://spec.matrix.org/v1.18/client-server-api/#account-locking
360    UserLocked,
361
362    /// `M_USER_SUSPENDED`
363    ///
364    /// The account has been [suspended] and can only be used for limited actions at this time.
365    ///
366    /// [suspended]: https://spec.matrix.org/v1.18/client-server-api/#account-suspension
367    UserSuspended,
368
369    /// `M_WEAK_PASSWORD`
370    ///
371    /// The password was [rejected] by the server for being too weak.
372    ///
373    /// [rejected]: https://spec.matrix.org/v1.18/client-server-api/#password-management
374    WeakPassword,
375
376    /// `M_WRONG_ROOM_KEYS_VERSION`
377    ///
378    /// The version of the [room keys backup] provided in the request does not match the current
379    /// backup version.
380    ///
381    /// [room keys backup]: https://spec.matrix.org/v1.18/client-server-api/#server-side-key-backups
382    WrongRoomKeysVersion(WrongRoomKeysVersionErrorData),
383
384    #[doc(hidden)]
385    _Custom(CustomErrorKind),
386}
387
388impl ErrorKind {
389    /// Get the [`ErrorCode`] for this `ErrorKind`.
390    pub fn errcode(&self) -> ErrorCode {
391        match self {
392            ErrorKind::AppserviceLoginUnsupported => ErrorCode::AppserviceLoginUnsupported,
393            ErrorKind::BadAlias => ErrorCode::BadAlias,
394            ErrorKind::BadJson => ErrorCode::BadJson,
395            ErrorKind::BadState => ErrorCode::BadState,
396            ErrorKind::BadStatus(_) => ErrorCode::BadStatus,
397            ErrorKind::CannotLeaveServerNoticeRoom => ErrorCode::CannotLeaveServerNoticeRoom,
398            ErrorKind::CannotOverwriteMedia => ErrorCode::CannotOverwriteMedia,
399            ErrorKind::CaptchaInvalid => ErrorCode::CaptchaInvalid,
400            ErrorKind::CaptchaNeeded => ErrorCode::CaptchaNeeded,
401            #[cfg(feature = "unstable-msc4306")]
402            ErrorKind::ConflictingUnsubscription => ErrorCode::ConflictingUnsubscription,
403            ErrorKind::ConnectionFailed => ErrorCode::ConnectionFailed,
404            ErrorKind::ConnectionTimeout => ErrorCode::ConnectionTimeout,
405            ErrorKind::DuplicateAnnotation => ErrorCode::DuplicateAnnotation,
406            ErrorKind::Exclusive => ErrorCode::Exclusive,
407            ErrorKind::Forbidden => ErrorCode::Forbidden,
408            ErrorKind::GuestAccessForbidden => ErrorCode::GuestAccessForbidden,
409            ErrorKind::IncompatibleRoomVersion(_) => ErrorCode::IncompatibleRoomVersion,
410            ErrorKind::InvalidParam => ErrorCode::InvalidParam,
411            ErrorKind::InvalidRoomState => ErrorCode::InvalidRoomState,
412            ErrorKind::InvalidUsername => ErrorCode::InvalidUsername,
413            ErrorKind::InviteBlocked => ErrorCode::InviteBlocked,
414            ErrorKind::LimitExceeded(_) => ErrorCode::LimitExceeded,
415            ErrorKind::MissingParam => ErrorCode::MissingParam,
416            ErrorKind::MissingToken => ErrorCode::MissingToken,
417            ErrorKind::NotFound => ErrorCode::NotFound,
418            #[cfg(feature = "unstable-msc4306")]
419            ErrorKind::NotInThread => ErrorCode::NotInThread,
420            ErrorKind::NotJson => ErrorCode::NotJson,
421            ErrorKind::NotYetUploaded => ErrorCode::NotYetUploaded,
422            ErrorKind::ResourceLimitExceeded(_) => ErrorCode::ResourceLimitExceeded,
423            ErrorKind::RoomInUse => ErrorCode::RoomInUse,
424            ErrorKind::ServerNotTrusted => ErrorCode::ServerNotTrusted,
425            ErrorKind::ThreepidAuthFailed => ErrorCode::ThreepidAuthFailed,
426            ErrorKind::ThreepidDenied => ErrorCode::ThreepidDenied,
427            ErrorKind::ThreepidInUse => ErrorCode::ThreepidInUse,
428            ErrorKind::ThreepidMediumNotSupported => ErrorCode::ThreepidMediumNotSupported,
429            ErrorKind::ThreepidNotFound => ErrorCode::ThreepidNotFound,
430            ErrorKind::TokenIncorrect => ErrorCode::TokenIncorrect,
431            ErrorKind::TooLarge => ErrorCode::TooLarge,
432            ErrorKind::UnableToAuthorizeJoin => ErrorCode::UnableToAuthorizeJoin,
433            ErrorKind::UnableToGrantJoin => ErrorCode::UnableToGrantJoin,
434            #[cfg(feature = "unstable-msc3843")]
435            ErrorKind::Unactionable => ErrorCode::Unactionable,
436            ErrorKind::Unauthorized => ErrorCode::Unauthorized,
437            ErrorKind::Unknown => ErrorCode::Unknown,
438            #[cfg(feature = "unstable-msc4186")]
439            ErrorKind::UnknownPos => ErrorCode::UnknownPos,
440            ErrorKind::UnknownToken(_) => ErrorCode::UnknownToken,
441            ErrorKind::Unrecognized => ErrorCode::Unrecognized,
442            ErrorKind::UnsupportedRoomVersion => ErrorCode::UnsupportedRoomVersion,
443            ErrorKind::UrlNotSet => ErrorCode::UrlNotSet,
444            ErrorKind::UserDeactivated => ErrorCode::UserDeactivated,
445            ErrorKind::UserInUse => ErrorCode::UserInUse,
446            ErrorKind::UserLimitExceeded(_) => ErrorCode::UserLimitExceeded,
447            ErrorKind::UserLocked => ErrorCode::UserLocked,
448            ErrorKind::UserSuspended => ErrorCode::UserSuspended,
449            ErrorKind::WeakPassword => ErrorCode::WeakPassword,
450            ErrorKind::WrongRoomKeysVersion(_) => ErrorCode::WrongRoomKeysVersion,
451            ErrorKind::_Custom(CustomErrorKind { errcode, .. }) => errcode.as_str().into(),
452        }
453    }
454
455    /// Get the JSON data for this `ErrorKind`, if it uses a custom error code.
456    pub fn custom_json_data(&self) -> Option<&JsonObject> {
457        as_variant!(self, Self::_Custom(error_kind) => &error_kind.data)
458    }
459}
460
461/// Data for the `M_BAD_STATUS` [`ErrorKind`].
462#[derive(Clone, Debug, Default, PartialEq, Eq)]
463#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
464pub struct BadStatusErrorData {
465    /// The HTTP status code of the response.
466    pub status: Option<http::StatusCode>,
467
468    /// The body of the response.
469    pub body: Option<String>,
470}
471
472impl BadStatusErrorData {
473    /// Construct a new empty `BadStatusErrorData`.
474    pub fn new() -> Self {
475        Self::default()
476    }
477}
478
479/// Data for the `M_INCOMPATIBLE_ROOM_VERSION` [`ErrorKind`].
480#[derive(Clone, Debug, PartialEq, Eq)]
481#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
482pub struct IncompatibleRoomVersionErrorData {
483    /// The room's version.
484    pub room_version: RoomVersionId,
485}
486
487impl IncompatibleRoomVersionErrorData {
488    /// Construct a new `IncompatibleRoomVersionErrorData` with the given room version.
489    pub fn new(room_version: RoomVersionId) -> Self {
490        Self { room_version }
491    }
492}
493
494/// Data for the `M_LIMIT_EXCEEDED` [`ErrorKind`].
495#[derive(Clone, Debug, Default, PartialEq, Eq)]
496#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
497pub struct LimitExceededErrorData {
498    /// How long a client should wait before they can try again.
499    pub retry_after: Option<RetryAfter>,
500}
501
502impl LimitExceededErrorData {
503    /// Construct a new empty `LimitExceededErrorData`.
504    pub fn new() -> Self {
505        Self::default()
506    }
507}
508
509/// How long a client should wait before it tries again.
510#[derive(Debug, Clone, Copy, PartialEq, Eq)]
511#[allow(clippy::exhaustive_enums)]
512pub enum RetryAfter {
513    /// The client should wait for the given duration.
514    ///
515    /// This variant should be preferred for backwards compatibility, as it will also populate the
516    /// `retry_after_ms` field in the body of the response.
517    Delay(Duration),
518    /// The client should wait for the given date and time.
519    DateTime(SystemTime),
520}
521
522impl TryFrom<&http::HeaderValue> for RetryAfter {
523    type Error = HeaderDeserializationError;
524
525    fn try_from(value: &http::HeaderValue) -> Result<Self, Self::Error> {
526        if value.as_bytes().iter().all(|b| b.is_ascii_digit()) {
527            // It should be a duration.
528            Ok(Self::Delay(Duration::from_secs(u64::from_str(value.to_str()?)?)))
529        } else {
530            // It should be a date.
531            Ok(Self::DateTime(http_date_to_system_time(value)?))
532        }
533    }
534}
535
536impl TryFrom<&RetryAfter> for http::HeaderValue {
537    type Error = HeaderSerializationError;
538
539    fn try_from(value: &RetryAfter) -> Result<Self, Self::Error> {
540        match value {
541            RetryAfter::Delay(duration) => Ok(duration.as_secs().into()),
542            RetryAfter::DateTime(time) => system_time_to_http_date(time),
543        }
544    }
545}
546
547/// Data for the `M_RESOURCE_LIMIT_EXCEEDED` [`ErrorKind`].
548#[derive(Clone, Debug, PartialEq, Eq)]
549#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
550pub struct ResourceLimitExceededErrorData {
551    /// A URI giving a contact method for the server administrator.
552    pub admin_contact: String,
553}
554
555impl ResourceLimitExceededErrorData {
556    /// Construct a new `ResourceLimitExceededErrorData` with the given admin contact URI.
557    pub fn new(admin_contact: String) -> Self {
558        Self { admin_contact }
559    }
560}
561
562/// Data for the `M_UNKNOWN_TOKEN` [`ErrorKind`].
563#[derive(Clone, Debug, Default, PartialEq, Eq)]
564#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
565pub struct UnknownTokenErrorData {
566    /// If this is `true`, the client is in a "[soft logout]" state, i.e. the server requires
567    /// re-authentication but the session is not invalidated. The client can acquire a new
568    /// access token by specifying the device ID it is already using to the login API.
569    ///
570    /// [soft logout]: https://spec.matrix.org/v1.18/client-server-api/#soft-logout
571    pub soft_logout: bool,
572}
573
574impl UnknownTokenErrorData {
575    /// Construct a new `UnknownTokenErrorData` with `soft_logout` set to `false`.
576    pub fn new() -> Self {
577        Self::default()
578    }
579}
580
581/// Data for the `M_USER_LIMIT_EXCEEDED` [`ErrorKind`].
582#[derive(Clone, Debug, PartialEq, Eq)]
583#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
584pub struct UserLimitExceededErrorData {
585    /// A URI that the client can present to the user to provide more context on the encountered
586    /// limit and, if applicable, guidance on how to increase the limit.
587    ///
588    /// The homeserver MAY return different values depending on the type of limit reached.
589    pub info_uri: String,
590
591    /// Whether the specific limit encountered can be increased.
592    ///
593    /// If `true`, it indicates that the specific limit encountered can be increased, for example
594    /// by upgrading the user’s account tier. If `false`, the limit is a hard limit that cannot be
595    /// increased.
596    ///
597    /// Defaults to `false`.
598    pub can_upgrade: bool,
599}
600
601impl UserLimitExceededErrorData {
602    /// Construct a new `UserLimitExceededErrorData` with the given URI.
603    pub fn new(info_uri: String) -> Self {
604        Self { info_uri, can_upgrade: false }
605    }
606}
607
608/// Data for the `M_WRONG_ROOM_KEYS_VERSION` [`ErrorKind`].
609#[derive(Clone, Debug, PartialEq, Eq)]
610#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
611pub struct WrongRoomKeysVersionErrorData {
612    /// The currently active backup version.
613    pub current_version: String,
614}
615
616impl WrongRoomKeysVersionErrorData {
617    /// Construct a new `WrongRoomKeysVersionErrorData` with the given current active backup
618    /// version.
619    pub fn new(current_version: String) -> Self {
620        Self { current_version }
621    }
622}
623
624/// A custom error kind.
625#[doc(hidden)]
626#[derive(Clone, Debug, PartialEq, Eq)]
627pub struct CustomErrorKind {
628    /// The error code.
629    pub(super) errcode: String,
630
631    /// The data for the error.
632    pub(super) data: JsonObject,
633}
634
635/// The possible [error codes] defined in the Matrix spec.
636///
637/// [error codes]: https://spec.matrix.org/v1.18/client-server-api/#standard-error-response
638#[derive(Clone, StringEnum)]
639#[non_exhaustive]
640#[ruma_enum(rename_all(prefix = "M_", rule = "SCREAMING_SNAKE_CASE"))]
641// Please keep the variants sorted alphabetically.
642pub enum ErrorCode {
643    /// `M_APPSERVICE_LOGIN_UNSUPPORTED`
644    ///
645    /// An application service used the [`m.login.application_service`] type an endpoint from the
646    /// [legacy authentication API] in a way that is not supported by the homeserver, because the
647    /// server only supports the [OAuth 2.0 API].
648    ///
649    /// [`m.login.application_service`]: https://spec.matrix.org/v1.18/application-service-api/#server-admin-style-permissions
650    /// [legacy authentication API]: https://spec.matrix.org/v1.18/client-server-api/#legacy-api
651    /// [OAuth 2.0 API]: https://spec.matrix.org/v1.18/client-server-api/#oauth-20-api
652    AppserviceLoginUnsupported,
653
654    /// `M_BAD_ALIAS`
655    ///
656    /// One or more [room aliases] within the `m.room.canonical_alias` event do not point to the
657    /// room ID for which the state event is to be sent to.
658    ///
659    /// [room aliases]: https://spec.matrix.org/v1.18/client-server-api/#room-aliases
660    BadAlias,
661
662    /// `M_BAD_JSON`
663    ///
664    /// The request contained valid JSON, but it was malformed in some way, e.g. missing required
665    /// keys, invalid values for keys.
666    BadJson,
667
668    /// `M_BAD_STATE`
669    ///
670    /// The state change requested cannot be performed, such as attempting to unban a user who is
671    /// not banned.
672    BadState,
673
674    /// `M_BAD_STATUS`
675    ///
676    /// The application service returned a bad status.
677    BadStatus,
678
679    /// `M_CANNOT_LEAVE_SERVER_NOTICE_ROOM`
680    ///
681    /// The user is unable to reject an invite to join the [server notices] room.
682    ///
683    /// [server notices]: https://spec.matrix.org/v1.18/client-server-api/#server-notices
684    CannotLeaveServerNoticeRoom,
685
686    /// `M_CANNOT_OVERWRITE_MEDIA`
687    ///
688    /// The `PUT /_matrix/media/*/upload/{serverName}/{mediaId}` endpoint was called with a media ID
689    /// that already has content.
690    CannotOverwriteMedia,
691
692    /// `M_CAPTCHA_INVALID`
693    ///
694    /// The Captcha provided did not match what was expected.
695    CaptchaInvalid,
696
697    /// `M_CAPTCHA_NEEDED`
698    ///
699    /// A Captcha is required to complete the request.
700    CaptchaNeeded,
701
702    /// `M_CONFLICTING_UNSUBSCRIPTION`
703    ///
704    /// Part of [MSC4306]: an automatic thread subscription has been skipped by the server, because
705    /// the user unsubsubscribed after the indicated subscribed-to event.
706    ///
707    /// [MSC4306]: https://github.com/matrix-org/matrix-spec-proposals/pull/4306
708    #[cfg(feature = "unstable-msc4306")]
709    #[ruma_enum(rename = "IO.ELEMENT.MSC4306.M_CONFLICTING_UNSUBSCRIPTION")]
710    ConflictingUnsubscription,
711
712    /// `M_CONNECTION_FAILED`
713    ///
714    /// The connection to the application service failed.
715    ConnectionFailed,
716
717    /// `M_CONNECTION_TIMEOUT`
718    ///
719    /// The connection to the application service timed out.
720    ConnectionTimeout,
721
722    /// `M_DUPLICATE_ANNOTATION`
723    ///
724    /// The request is an attempt to send a [duplicate annotation].
725    ///
726    /// [duplicate annotation]: https://spec.matrix.org/v1.18/client-server-api/#avoiding-duplicate-annotations
727    DuplicateAnnotation,
728
729    /// `M_EXCLUSIVE`
730    ///
731    /// The resource being requested is reserved by an application service, or the application
732    /// service making the request has not created the resource.
733    Exclusive,
734
735    /// `M_FORBIDDEN`
736    ///
737    /// Forbidden access, e.g. joining a room without permission, failed login.
738    Forbidden,
739
740    /// `M_GUEST_ACCESS_FORBIDDEN`
741    ///
742    /// The room or resource does not permit [guests] to access it.
743    ///
744    /// [guests]: https://spec.matrix.org/v1.18/client-server-api/#guest-access
745    GuestAccessForbidden,
746
747    /// `M_INCOMPATIBLE_ROOM_VERSION`
748    ///
749    /// The client attempted to join a room that has a version the server does not support.
750    IncompatibleRoomVersion,
751
752    /// `M_INVALID_PARAM`
753    ///
754    /// A parameter that was specified has the wrong value. For example, the server expected an
755    /// integer and instead received a string.
756    InvalidParam,
757
758    /// `M_INVALID_ROOM_STATE`
759    ///
760    /// The initial state implied by the parameters to the `POST /_matrix/client/*/createRoom`
761    /// request is invalid, e.g. the user's `power_level` is set below that necessary to set the
762    /// room name.
763    InvalidRoomState,
764
765    /// `M_INVALID_USERNAME`
766    ///
767    /// The desired user name is not valid.
768    InvalidUsername,
769
770    /// `M_INVITE_BLOCKED`
771    ///
772    /// The invite was interdicted by moderation tools or configured access controls without having
773    /// been witnessed by the invitee.
774    ///
775    /// Unstable prefix intentionally shared with MSC4155 for compatibility.
776    #[ruma_enum(alias = "ORG.MATRIX.MSC4155.INVITE_BLOCKED")]
777    InviteBlocked,
778
779    /// `M_LIMIT_EXCEEDED`
780    ///
781    /// The request has been refused due to [rate limiting]: too many requests have been sent in a
782    /// short period of time.
783    ///
784    /// [rate limiting]: https://spec.matrix.org/v1.18/client-server-api/#rate-limiting
785    LimitExceeded,
786
787    /// `M_MISSING_PARAM`
788    ///
789    /// A required parameter was missing from the request.
790    MissingParam,
791
792    /// `M_MISSING_TOKEN`
793    ///
794    /// No [access token] was specified for the request, but one is required.
795    ///
796    /// [access token]: https://spec.matrix.org/v1.18/client-server-api/#client-authentication
797    MissingToken,
798
799    /// `M_NOT_FOUND`
800    ///
801    /// No resource was found for this request.
802    NotFound,
803
804    /// `M_NOT_IN_THREAD`
805    ///
806    /// Part of [MSC4306]: an automatic thread subscription was set to an event ID that isn't part
807    /// of the subscribed-to thread.
808    ///
809    /// [MSC4306]: https://github.com/matrix-org/matrix-spec-proposals/pull/4306
810    #[cfg(feature = "unstable-msc4306")]
811    #[ruma_enum(rename = "IO.ELEMENT.MSC4306.M_NOT_IN_THREAD")]
812    NotInThread,
813
814    /// `M_NOT_JSON`
815    ///
816    /// The request did not contain valid JSON.
817    NotJson,
818
819    /// `M_NOT_YET_UPLOADED`
820    ///
821    /// An `mxc:` URI generated with the `POST /_matrix/media/*/create` endpoint was used and the
822    /// content is not yet available.
823    NotYetUploaded,
824
825    /// `M_RESOURCE_LIMIT_EXCEEDED`
826    ///
827    /// The request cannot be completed because the homeserver has reached a resource limit imposed
828    /// on it. For example, a homeserver held in a shared hosting environment may reach a resource
829    /// limit if it starts using too much memory or disk space.
830    ResourceLimitExceeded,
831
832    /// `M_ROOM_IN_USE`
833    ///
834    /// The [room alias] specified in the `POST /_matrix/client/*/createRoom` request is already
835    /// taken.
836    ///
837    /// [room alias]: https://spec.matrix.org/v1.18/client-server-api/#room-aliases
838    RoomInUse,
839
840    /// `M_SERVER_NOT_TRUSTED`
841    ///
842    /// The client's request used a third-party server, e.g. identity server, that this server does
843    /// not trust.
844    ServerNotTrusted,
845
846    /// `M_THREEPID_AUTH_FAILED`
847    ///
848    /// Authentication could not be performed on the [third-party identifier].
849    ///
850    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
851    ThreepidAuthFailed,
852
853    /// `M_THREEPID_DENIED`
854    ///
855    /// The server does not permit this [third-party identifier]. This may happen if the server
856    /// only permits, for example, email addresses from a particular domain.
857    ///
858    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
859    ThreepidDenied,
860
861    /// `M_THREEPID_IN_USE`
862    ///
863    /// The [third-party identifier] is already in use by another user.
864    ///
865    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
866    ThreepidInUse,
867
868    /// `M_THREEPID_MEDIUM_NOT_SUPPORTED`
869    ///
870    /// The homeserver does not support adding a [third-party identifier] of the given medium.
871    ///
872    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
873    ThreepidMediumNotSupported,
874
875    /// `M_THREEPID_NOT_FOUND`
876    ///
877    /// No account matching the given [third-party identifier] could be found.
878    ///
879    /// [third-party identifier]: https://spec.matrix.org/v1.18/client-server-api/#adding-account-administrative-contact-information
880    ThreepidNotFound,
881
882    /// `M_TOKEN_INCORRECT`
883    ///
884    /// The token that the user entered to validate the session is incorrect.
885    TokenIncorrect,
886
887    /// `M_TOO_LARGE`
888    ///
889    /// The request or entity was too large.
890    TooLarge,
891
892    /// `M_UNABLE_TO_AUTHORISE_JOIN`
893    ///
894    /// The room is [restricted] and none of the conditions can be validated by the homeserver.
895    /// This can happen if the homeserver does not know about any of the rooms listed as
896    /// conditions, for example.
897    ///
898    /// [restricted]: https://spec.matrix.org/v1.18/client-server-api/#restricted-rooms
899    #[ruma_enum(rename = "M_UNABLE_TO_AUTHORISE_JOIN")]
900    UnableToAuthorizeJoin,
901
902    /// `M_UNABLE_TO_GRANT_JOIN`
903    ///
904    /// A different server should be attempted for the join. This is typically because the resident
905    /// server can see that the joining user satisfies one or more conditions, such as in the case
906    /// of [restricted rooms], but the resident server would be unable to meet the authorization
907    /// rules.
908    ///
909    /// [restricted rooms]: https://spec.matrix.org/v1.18/client-server-api/#restricted-rooms
910    UnableToGrantJoin,
911
912    /// `M_UNACTIONABLE`
913    ///
914    /// The server does not want to handle the [federated report].
915    ///
916    /// [federated report]: https://github.com/matrix-org/matrix-spec-proposals/pull/3843
917    #[cfg(feature = "unstable-msc3843")]
918    Unactionable,
919
920    /// `M_UNAUTHORIZED`
921    ///
922    /// The request was not correctly authorized. Usually due to login failures.
923    Unauthorized,
924
925    /// `M_UNKNOWN`
926    ///
927    /// An unknown error has occurred.
928    Unknown,
929
930    /// `M_UNKNOWN_POS`
931    ///
932    /// The sliding sync ([MSC4186]) connection was expired by the server.
933    ///
934    /// [MSC4186]: https://github.com/matrix-org/matrix-spec-proposals/pull/4186
935    #[cfg(feature = "unstable-msc4186")]
936    UnknownPos,
937
938    /// `M_UNKNOWN_TOKEN`
939    ///
940    /// The [access or refresh token] specified was not recognized.
941    ///
942    /// [access or refresh token]: https://spec.matrix.org/v1.18/client-server-api/#client-authentication
943    UnknownToken,
944
945    /// `M_UNRECOGNIZED`
946    ///
947    /// The server did not understand the request.
948    ///
949    /// This is expected to be returned with a 404 HTTP status code if the endpoint is not
950    /// implemented or a 405 HTTP status code if the endpoint is implemented, but the incorrect
951    /// HTTP method is used.
952    Unrecognized,
953
954    /// `M_UNSUPPORTED_ROOM_VERSION`
955    UnsupportedRoomVersion,
956
957    /// `M_URL_NOT_SET`
958    ///
959    /// The application service doesn't have a URL configured.
960    UrlNotSet,
961
962    /// `M_USER_DEACTIVATED`
963    ///
964    /// The user ID associated with the request has been deactivated.
965    UserDeactivated,
966
967    /// `M_USER_IN_USE`
968    ///
969    /// The desired user ID is already taken.
970    UserInUse,
971
972    /// `M_USER_LIMIT_EXCEEDED`
973    ///
974    /// The request cannot be completed because the user has exceeded (or the request would cause
975    /// them to exceed) a limit associated with their account. For example, a user may have reached
976    /// their allocated storage quota, reached a maximum number of allowed rooms, devices, or other
977    /// account-scoped resources, or exceeded usage limits for specific features.
978    UserLimitExceeded,
979
980    /// `M_USER_LOCKED`
981    ///
982    /// The account has been [locked] and cannot be used at this time.
983    ///
984    /// [locked]: https://spec.matrix.org/v1.18/client-server-api/#account-locking
985    UserLocked,
986
987    /// `M_USER_SUSPENDED`
988    ///
989    /// The account has been [suspended] and can only be used for limited actions at this time.
990    ///
991    /// [suspended]: https://spec.matrix.org/v1.18/client-server-api/#account-suspension
992    UserSuspended,
993
994    /// `M_WEAK_PASSWORD`
995    ///
996    /// The password was [rejected] by the server for being too weak.
997    ///
998    /// [rejected]: https://spec.matrix.org/v1.18/client-server-api/#password-management
999    WeakPassword,
1000
1001    /// `M_WRONG_ROOM_KEYS_VERSION`
1002    ///
1003    /// The version of the [room keys backup] provided in the request does not match the current
1004    /// backup version.
1005    ///
1006    /// [room keys backup]: https://spec.matrix.org/v1.18/client-server-api/#server-side-key-backups
1007    WrongRoomKeysVersion,
1008
1009    #[doc(hidden)]
1010    _Custom(PrivOwnedStr),
1011}