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}