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