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