Skip to main content

openmls/group/
errors.rs

1//! # MLS group errors
2//!
3//! This module contains errors that originate at lower levels and are partially re-exported in errors thrown by functions of the `MlsGroup` API.
4
5use thiserror::Error;
6
7#[cfg(feature = "extensions-draft-08")]
8use super::public_group::errors::ApplyAppDataUpdateError;
9
10pub use super::mls_group::errors::*;
11use super::public_group::errors::CreationFromExternalError;
12use crate::{
13    ciphersuite::signable::SignatureError,
14    error::LibraryError,
15    extensions::errors::{ExtensionError, InvalidExtensionError},
16    framing::errors::MessageDecryptionError,
17    group::commit_builder::external_commits::ExternalCommitBuilderError,
18    key_packages::errors::{KeyPackageExtensionSupportError, KeyPackageVerifyError},
19    messages::{group_info::GroupInfoError, GroupSecretsError},
20    prelude::ExtensionType,
21    schedule::{errors::PskError, PreSharedKeyId},
22    treesync::errors::*,
23};
24
25#[cfg(doc)]
26use crate::{group::GroupId, treesync::LeafNodeParameters};
27
28/// Welcome error
29#[derive(Error, Debug, PartialEq, Clone)]
30pub enum WelcomeError<StorageError> {
31    /// See [`GroupSecretsError`] for more details.
32    #[error(transparent)]
33    GroupSecrets(#[from] GroupSecretsError),
34    /// Private part of `init_key` not found in key store.
35    #[error("Private part of `init_key` not found in key store.")]
36    PrivateInitKeyNotFound,
37    /// See [`LibraryError`] for more details.
38    #[error(transparent)]
39    LibraryError(#[from] LibraryError),
40    /// Ciphersuites in Welcome and key package bundle don't match.
41    #[error("Ciphersuites in Welcome and key package bundle don't match.")]
42    CiphersuiteMismatch,
43    /// See [`GroupInfoError`] for more details.
44    #[error(transparent)]
45    GroupInfo(#[from] GroupInfoError),
46    /// No joiner secret found in the Welcome message.
47    #[error("No joiner secret found in the Welcome message.")]
48    JoinerSecretNotFound,
49    /// No ratchet tree available to build initial tree after receiving a Welcome message.
50    #[error("No ratchet tree available to build initial tree after receiving a Welcome message.")]
51    MissingRatchetTree,
52    /// The computed confirmation tag does not match the expected one.
53    #[error("The computed confirmation tag does not match the expected one.")]
54    ConfirmationTagMismatch,
55    /// The signature on the GroupInfo is not valid.
56    #[error("The signature on the GroupInfo is not valid.")]
57    InvalidGroupInfoSignature,
58    /// We don't support the version of the group we are trying to join.
59    #[error("We don't support the version of the group we are trying to join.")]
60    UnsupportedMlsVersion,
61    /// We don't support all capabilities of the group.
62    #[error("We don't support all capabilities of the group.")]
63    UnsupportedCapability,
64    /// Sender not found in tree.
65    #[error("Sender not found in tree.")]
66    UnknownSender,
67    /// The provided message is not a Welcome message.
68    #[error("Not a Welcome message.")]
69    NotAWelcomeMessage,
70    /// Malformed Welcome message.
71    #[error("Malformed Welcome message.")]
72    MalformedWelcomeMessage,
73    /// Could not decrypt the Welcome message.
74    #[error("Could not decrypt the Welcome message.")]
75    UnableToDecrypt,
76    /// Unsupported extensions found in the GroupContext or KeyPackage of another member.
77    #[error("Unsupported extensions found in the GroupContext or KeyPackage of another member.")]
78    UnsupportedExtensions,
79    /// See [`PskError`] for more details.
80    #[error(transparent)]
81    Psk(#[from] PskError),
82    /// No matching encryption key was found in the key store.
83    #[error("No matching encryption key was found in the key store.")]
84    NoMatchingEncryptionKey,
85    /// No matching key package was found in the key store.
86    #[error("No matching key package was found in the key store.")]
87    NoMatchingKeyPackage,
88    /// This error indicates the public tree is invalid. See [`PublicTreeError`] for more details.
89    #[error(transparent)]
90    PublicTreeError(#[from] PublicTreeError),
91    /// This error indicates the public tree is invalid. See
92    /// [`CreationFromExternalError`] for more details.
93    #[error(transparent)]
94    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
95    /// This error indicates the leaf node is invalid. See [`LeafNodeValidationError`] for more details.
96    #[error(transparent)]
97    LeafNodeValidation(#[from] LeafNodeValidationError),
98    /// This error indicates that an error occurred while reading or writing from/to storage.
99    #[error("An error occurred when querying storage")]
100    StorageError(StorageError),
101    /// A group with this [`GroupId`] already exists.
102    #[error("A group with this [`GroupId`] already exists.")]
103    GroupAlreadyExists,
104}
105
106/// External Commit error
107#[derive(Error, Debug, PartialEq, Clone)]
108pub enum ExternalCommitError<StorageError> {
109    /// See [`LibraryError`] for more details.
110    #[error(transparent)]
111    LibraryError(#[from] LibraryError),
112    /// No ratchet tree available to build initial tree.
113    #[error("No ratchet tree available to build initial tree.")]
114    MissingRatchetTree,
115    /// No external_pub extension available to join group by external commit.
116    #[error("No external_pub extension available to join group by external commit.")]
117    MissingExternalPub,
118    /// We don't support the ciphersuite of the group we are trying to join.
119    #[error("We don't support the ciphersuite of the group we are trying to join.")]
120    UnsupportedCiphersuite,
121    /// Sender not found in tree.
122    #[error("Sender not found in tree.")]
123    UnknownSender,
124    /// The signature over the given group info is invalid.
125    #[error("The signature over the given group info is invalid.")]
126    InvalidGroupInfoSignature,
127    /// Error creating external commit.
128    #[error("Error creating external commit.")]
129    CommitError(#[from] CreateCommitError),
130    /// This error indicates the public tree is invalid. See
131    /// [`CreationFromExternalError`] for more details.
132    #[error(transparent)]
133    PublicGroupError(#[from] CreationFromExternalError<StorageError>),
134    /// Credential is missing from external commit.
135    #[error("Credential is missing from external commit.")]
136    MissingCredential,
137    /// An erorr occurred when writing group to storage
138    #[error("An error occurred when writing group to storage.")]
139    StorageError(StorageError),
140}
141
142impl<StorageError> From<ExternalCommitBuilderError<StorageError>>
143    for ExternalCommitError<StorageError>
144{
145    fn from(error: ExternalCommitBuilderError<StorageError>) -> Self {
146        match error {
147            ExternalCommitBuilderError::LibraryError(library_error) => {
148                ExternalCommitError::LibraryError(library_error)
149            }
150            ExternalCommitBuilderError::MissingRatchetTree => {
151                ExternalCommitError::MissingRatchetTree
152            }
153            ExternalCommitBuilderError::MissingExternalPub => {
154                ExternalCommitError::MissingExternalPub
155            }
156            ExternalCommitBuilderError::UnsupportedCiphersuite => {
157                ExternalCommitError::UnsupportedCiphersuite
158            }
159            ExternalCommitBuilderError::PublicGroupError(creation_from_external_error) => {
160                ExternalCommitError::PublicGroupError(creation_from_external_error)
161            }
162            ExternalCommitBuilderError::StorageError(error) => {
163                ExternalCommitError::StorageError(error)
164            }
165            // These should not happen since `join_by_external_commit` doesn't
166            // take proposals as input.
167            ExternalCommitBuilderError::InvalidProposal(e) => {
168                log::error!("Error validating proposal in external commit: {e}");
169                ExternalCommitError::LibraryError(LibraryError::custom(
170                    "Error creating external commit",
171                ))
172            }
173        }
174    }
175}
176
177impl<StorageError> From<ExternalCommitBuilderFinalizeError<StorageError>>
178    for ExternalCommitError<StorageError>
179{
180    fn from(error: ExternalCommitBuilderFinalizeError<StorageError>) -> Self {
181        match error {
182            ExternalCommitBuilderFinalizeError::LibraryError(library_error) => {
183                ExternalCommitError::LibraryError(library_error)
184            }
185            ExternalCommitBuilderFinalizeError::StorageError(error) => {
186                ExternalCommitError::StorageError(error)
187            }
188            ExternalCommitBuilderFinalizeError::MergeCommitError(e) => {
189                log::error!("Error merging external commit: {e}");
190                // This shouldn't happen, since we merge our own external
191                // commit.
192                ExternalCommitError::LibraryError(LibraryError::custom(
193                    "Error merging external commit",
194                ))
195            }
196        }
197    }
198}
199
200/// Stage Commit error
201#[derive(Error, Debug, PartialEq, Clone)]
202pub enum StageCommitError {
203    /// See [`LibraryError`] for more details.
204    #[error(transparent)]
205    LibraryError(#[from] LibraryError),
206    /// The epoch of the group context and PublicMessage didn't match.
207    #[error("The epoch of the group context and PublicMessage didn't match.")]
208    EpochMismatch,
209    /// The Commit was created by this client.
210    #[error("The Commit was created by this client.")]
211    OwnCommit,
212    /// stage_commit was called with an PublicMessage that is not a Commit.
213    #[error("stage_commit was called with an PublicMessage that is not a Commit.")]
214    WrongPlaintextContentType,
215    /// Unable to verify the leaf node signature.
216    #[error("Unable to verify the leaf node signature.")]
217    PathLeafNodeVerificationFailure,
218    /// Unable to determine commit path.
219    #[error("Unable to determine commit path.")]
220    RequiredPathNotFound,
221    /// The confirmation Tag is missing.
222    #[error("The confirmation Tag is missing.")]
223    ConfirmationTagMissing,
224    /// The confirmation tag is invalid.
225    #[error("The confirmation tag is invalid.")]
226    ConfirmationTagMismatch,
227    /// The committer can't remove themselves.
228    #[error("The committer can't remove themselves.")]
229    AttemptedSelfRemoval,
230    /// The proposal queue is missing a proposal for the commit.
231    #[error("The proposal queue is missing a proposal for the commit.")]
232    MissingProposal,
233    /// Missing own key to apply proposal.
234    #[error("Missing own key to apply proposal.")]
235    OwnKeyNotFound,
236    /// External Committer used the wrong index.
237    #[error("External Committer used the wrong index.")]
238    InconsistentSenderIndex,
239    /// The sender is of type external, which is not valid.
240    #[error("The sender is of type external, which is not valid.")]
241    SenderTypeExternal,
242    /// The sender is of type `NewMemberProposal`, which is not valid.
243    #[error("The sender is of type NewMemberProposal, which is not valid.")]
244    SenderTypeNewMemberProposal,
245    /// Too many new members: the tree is full.
246    #[error("Too many new members: the tree is full.")]
247    TooManyNewMembers,
248    /// See [`ProposalValidationError`] for more details.
249    #[error(transparent)]
250    ProposalValidationError(#[from] ProposalValidationError),
251    /// See [`PskError`] for more details.
252    #[error(transparent)]
253    PskError(#[from] PskError),
254    /// See [`ExternalCommitValidationError`] for more details.
255    #[error(transparent)]
256    ExternalCommitValidation(#[from] ExternalCommitValidationError),
257    /// See [`ApplyUpdatePathError`] for more details.
258    #[error(transparent)]
259    UpdatePathError(#[from] ApplyUpdatePathError),
260    /// Missing decryption key.
261    #[error("Missing decryption key.")]
262    MissingDecryptionKey,
263    /// See [`UpdatePathError`] for more details.
264    #[error(transparent)]
265    VerifiedUpdatePathError(#[from] UpdatePathError),
266    /// See [`GroupContextExtensionsProposalValidationError`] for more details.
267    #[error(transparent)]
268    GroupContextExtensionsProposalValidationError(
269        #[from] GroupContextExtensionsProposalValidationError,
270    ),
271    #[cfg(feature = "extensions-draft-08")]
272    /// See [`AppDataUpdateValidationError`] for more details.
273    #[error(transparent)]
274    AppDataUpdateValidationError(#[from] AppDataUpdateValidationError),
275    /// See [`LeafNodeValidationError`] for more details.
276    #[error(transparent)]
277    LeafNodeValidation(#[from] LeafNodeValidationError),
278    /// See [`ApplyAppDataUpdateError`] for more details.
279    #[cfg(feature = "extensions-draft-08")]
280    #[error(transparent)]
281    ApplyAppDataUpdateError(#[from] ApplyAppDataUpdateError),
282    /// Duplicate PSK Proposal.
283    #[error("Duplicate PSK proposal with PSK ID {0:?}.")]
284    DuplicatePskId(PreSharedKeyId),
285}
286
287/// Create commit error
288#[derive(Error, Debug, PartialEq, Clone)]
289pub enum CreateCommitError {
290    /// See [`LibraryError`] for more details.
291    #[error(transparent)]
292    LibraryError(#[from] LibraryError),
293    /// Missing own key to apply proposal.
294    #[error("Missing own key to apply proposal.")]
295    OwnKeyNotFound,
296    /// The Commit tried to remove self from the group. This is not possible.
297    #[error("The Commit tried to remove self from the group. This is not possible.")]
298    CannotRemoveSelf,
299    /// The proposal queue is missing a proposal for the commit.
300    #[error("The proposal queue is missing a proposal for the commit.")]
301    MissingProposal,
302    /// A proposal has the wrong sender type.
303    #[error("A proposal has the wrong sender type.")]
304    WrongProposalSenderType,
305    /// See [`PskError`] for more details.
306    #[error(transparent)]
307    PskError(#[from] PskError),
308    /// See [`ProposalValidationError`] for more details.
309    #[error(transparent)]
310    ProposalValidationError(#[from] ProposalValidationError),
311    /// See [`SignatureError`] for more details.
312    #[error(transparent)]
313    SignatureError(#[from] SignatureError),
314    /// Credential is missing from external commit.
315    #[error("Credential is missing from external commit.")]
316    MissingCredential,
317    /// This error indicates the public tree is invalid. See [`PublicTreeError`] for more details.
318    #[error(transparent)]
319    PublicTreeError(#[from] PublicTreeError),
320    /// See [`InvalidExtensionError`] for more details.
321    #[error(transparent)]
322    InvalidExtensionError(#[from] InvalidExtensionError),
323    #[cfg(feature = "extensions-draft-08")]
324    /// See [`AppDataUpdateValidationError`] for more details.
325    #[error(transparent)]
326    AppDataUpdateValidationError(#[from] AppDataUpdateValidationError),
327    /// See [`GroupContextExtensionsProposalValidationError`] for more details.
328    #[error(transparent)]
329    GroupContextExtensionsProposalValidationError(
330        #[from] GroupContextExtensionsProposalValidationError,
331    ),
332    /// See [`TreeSyncAddLeaf`] for more details.
333    #[error(transparent)]
334    TreeSyncAddLeaf(#[from] TreeSyncAddLeaf),
335    /// Invalid [`LeafNodeParameters`]. `[CredentialWithKey]` can't be set with new signer.
336    #[error("Invalid LeafNodeParameters. CredentialWithKey can't be set with new signer.")]
337    InvalidLeafNodeParameters,
338    /// Invalid external commit.
339    #[error("Invalid external commit.")]
340    InvalidExternalCommit(#[from] ExternalCommitValidationError),
341    /// See [`ApplyAppDataUpdateError`] for more details.
342    #[cfg(feature = "extensions-draft-08")]
343    #[error(transparent)]
344    ApplyAppDataUpdateError(#[from] ApplyAppDataUpdateError),
345    /// See [`LeafNodeValidationError`] for more details.
346    #[error(transparent)]
347    LeafNodeValidation(#[from] LeafNodeValidationError),
348}
349
350/// Stage commit error
351#[derive(Error, Debug, PartialEq, Clone)]
352pub enum CommitBuilderStageError<StorageError> {
353    /// See [`LibraryError`] for more details.
354    #[error(transparent)]
355    LibraryError(#[from] LibraryError),
356    /// Error interacting with storage.
357    #[error("Error interacting with storage.")]
358    KeyStoreError(StorageError),
359}
360
361/// Stage commit error
362#[derive(Error, Debug, PartialEq, Clone)]
363pub enum ExternalCommitBuilderFinalizeError<StorageError> {
364    /// See [`LibraryError`] for more details.
365    #[error(transparent)]
366    LibraryError(#[from] LibraryError),
367    /// Error interacting with storage.
368    #[error("Error interacting with storage.")]
369    StorageError(StorageError),
370    /// Error merging external commit.
371    #[error("Error merging external commit.")]
372    MergeCommitError(#[from] MergePendingCommitError<StorageError>),
373}
374
375/// Validation error
376#[derive(Error, Debug, PartialEq, Clone)]
377pub enum ValidationError {
378    /// See [`LibraryError`] for more details.
379    #[error(transparent)]
380    LibraryError(#[from] LibraryError),
381    /// Message group ID differs from the group's group ID.
382    #[error("Message group ID differs from the group's group ID.")]
383    WrongGroupId,
384    /// Message epoch differs from the group's epoch.
385    #[error("Message epoch differs from the group's epoch.")]
386    WrongEpoch,
387    /// The PublicMessage is not a Commit despite the sender begin of type [NewMemberCommit](crate::prelude::Sender::NewMemberCommit).
388    #[error("The PublicMessage is not a Commit despite the sender begin of type NewMemberCommit.")]
389    NotACommit,
390    /// The PublicMessage is not an External Add Proposal despite the sender begin of type [NewMemberProposal](crate::prelude::Sender::NewMemberProposal).
391    #[error("The PublicMessage is not an external Add proposal despite the sender begin of type NewMemberProposal.")]
392    NotAnExternalAddProposal,
393    /// The Commit doesn't have a path despite the sender being of type NewMemberCommit.
394    #[error("The Commit doesn't have a path despite the sender being of type NewMemberCommit.")]
395    NoPath,
396    /// The PublicMessage contains an application message but was not encrypted.
397    #[error("The PublicMessage contains an application message but was not encrypted.")]
398    UnencryptedApplicationMessage,
399    /// Sender is not part of the group.
400    #[error("Sender is not part of the group.")]
401    UnknownMember,
402    /// Membership tag is missing.
403    #[error("Membership tag is missing.")]
404    MissingMembershipTag,
405    /// Membership tag is invalid.
406    #[error("Membership tag is invalid.")]
407    InvalidMembershipTag,
408    /// The confirmation tag is missing.
409    #[error("The confirmation tag is missing.")]
410    MissingConfirmationTag,
411    /// Wrong wire format.
412    #[error("Wrong wire format.")]
413    WrongWireFormat,
414    /// Verifying the signature failed.
415    #[error("Verifying the signature failed.")]
416    InvalidSignature,
417    /// An application message was sent from an external sender.
418    #[error("An application message was sent from an external sender.")]
419    NonMemberApplicationMessage,
420    /// Could not decrypt the message
421    #[error(transparent)]
422    UnableToDecrypt(#[from] MessageDecryptionError),
423    /// The message is from an epoch too far in the past.
424    #[error("The message is from an epoch too far in the past.")]
425    NoPastEpochData,
426    /// The provided external sender is not authorized to send external proposals
427    #[error("The provided external sender is not authorized to send external proposals")]
428    UnauthorizedExternalSender,
429    /// The group doesn't contain external senders extension.
430    #[error("The group doesn't contain external senders extension")]
431    NoExternalSendersExtension,
432    /// The KeyPackage could not be validated.
433    #[error(transparent)]
434    KeyPackageVerifyError(#[from] KeyPackageVerifyError),
435    /// The UpdatePath could not be validated.
436    #[error(transparent)]
437    UpdatePathError(#[from] UpdatePathError),
438    /// Invalid LeafNode signature.
439    #[error("Invalid LeafNode signature.")]
440    InvalidLeafNodeSignature,
441    /// Invalid LeafNode source type
442    #[error("Invalid LeafNode source type")]
443    InvalidLeafNodeSourceType,
444    /// Invalid sender type.
445    #[error("Invalid sender type")]
446    InvalidSenderType,
447    /// The Commit includes update proposals from the committer.
448    #[error("The Commit includes update proposals from the committer.")]
449    CommitterIncludedOwnUpdate,
450    /// The ciphersuite in the KeyPackage of the Add proposal does not match the group context.
451    #[error(
452        "The ciphersuite in the KeyPackage of the Add proposal does not match the group context."
453    )]
454    InvalidAddProposalCiphersuite,
455    /// Cannot decrypt own messages because the necessary key has been deleted according to the deletion schedule.
456    #[error("Cannot decrypt own messages.")]
457    CannotDecryptOwnMessage,
458    /// See [`ExternalCommitValidationError`] for more details.
459    #[error(transparent)]
460    ExternalCommitValidation(#[from] ExternalCommitValidationError),
461    /// See [`InvalidExtensionError`]
462    #[error("Invalid extension")]
463    InvalidExtension(#[from] InvalidExtensionError),
464}
465
466/// Proposal validation error
467#[derive(Error, Debug, PartialEq, Clone)]
468pub enum ProposalValidationError {
469    /// See [`LibraryError`] for more details.
470    #[error(transparent)]
471    LibraryError(#[from] LibraryError),
472    /// The sender could not be matched to a member of the group.
473    #[error("The sender could not be matched to a member of the group.")]
474    UnknownMember,
475    /// Duplicate signature key in proposals and group.
476    #[error("Duplicate signature key in proposals and group.")]
477    DuplicateSignatureKey,
478    /// Duplicate encryption key in proposals and group.
479    #[error("Duplicate encryption key in proposals and group.")]
480    DuplicateEncryptionKey,
481    /// Duplicate init key in proposals.
482    #[error("Duplicate init key in proposals.")]
483    DuplicateInitKey,
484    /// The HPKE init and encryption keys are the same.
485    #[error("The HPKE init and encryption keys are the same.")]
486    InitEncryptionKeyCollision,
487    /// Duplicate remove proposals for the same member.
488    #[error("Duplicate remove proposals for the same member.")]
489    DuplicateMemberRemoval,
490    /// The remove proposal referenced a non-existing member.
491    #[error("The remove proposal referenced a non-existing member.")]
492    UnknownMemberRemoval,
493    /// Found an update from a non-member.
494    #[error("Found an update from a non-member.")]
495    UpdateFromNonMember,
496    /// The Commit includes update proposals from the committer.
497    #[error("The Commit includes update proposals from the committer.")]
498    CommitterIncludedOwnUpdate,
499    /// The capabilities of the add proposal are insufficient for this group.
500    #[error("The capabilities of the add proposal are insufficient for this group.")]
501    InsufficientCapabilities,
502    /// The add proposal's ciphersuite or protocol version do not match the ones in the group context.
503    #[error(
504        "The add proposal's ciphersuite or protocol version do not match the ones in the group context."
505    )]
506    InvalidAddProposalCiphersuiteOrVersion,
507    /// See [`PskError`] for more details.
508    #[error(transparent)]
509    Psk(#[from] PskError),
510    /// The proposal type is not supported by all group members.
511    #[error("The proposal type is not supported by all group members.")]
512    UnsupportedProposalType,
513    /// See [`LeafNodeValidationError`] for more details.
514    #[error(transparent)]
515    LeafNodeValidation(#[from] LeafNodeValidationError),
516    /// Regular Commits may not contain ExternalInit proposals, but one was found
517    #[error("Found ExternalInit proposal in regular commit")]
518    ExternalInitProposalInRegularCommit,
519}
520
521/// External Commit validaton error
522#[derive(Error, Debug, PartialEq, Clone)]
523pub enum ExternalCommitValidationError {
524    /// See [`LibraryError`] for more details.
525    #[error(transparent)]
526    LibraryError(#[from] LibraryError),
527    /// No ExternalInit proposal found.
528    #[error("No ExternalInit proposal found.")]
529    NoExternalInitProposals,
530    /// Multiple ExternalInit proposal found.
531    #[error("Multiple ExternalInit proposal found.")]
532    MultipleExternalInitProposals,
533    /// Found inline Add or Update proposals.
534    #[error("Found inline Add or Update proposals.")]
535    InvalidInlineProposals,
536    /// Found multiple inline Remove proposals.
537    #[error("Found multiple inline Remove proposals.")]
538    MultipleRemoveProposals,
539    /// Remove proposal targets the wrong group member.
540    #[error("Remove proposal targets the wrong group member.")]
541    InvalidRemoveProposal,
542    /// External Commit has to contain a path.
543    #[error("External Commit has to contain a path.")]
544    NoPath,
545    /// External commit contains referenced proposal
546    #[error("Found a referenced proposal in an External Commit.")]
547    ReferencedProposal,
548    /// External committer's leaf node does not support all group context extensions.
549    #[error("External committer's leaf node does not support all group context extensions.")]
550    UnsupportedGroupContextExtensions,
551}
552
553/// Create add proposal error
554#[derive(Error, Debug, PartialEq, Clone)]
555pub enum CreateAddProposalError {
556    /// See [`LibraryError`] for more details.
557    #[error(transparent)]
558    LibraryError(#[from] LibraryError),
559    /// See [`LeafNodeValidationError`] for more details.
560    #[error(transparent)]
561    LeafNodeValidation(#[from] LeafNodeValidationError),
562}
563
564// === Crate errors ===
565
566/// Proposal queue error
567#[derive(Error, Debug, PartialEq, Clone)]
568pub(crate) enum ProposalQueueError {
569    /// See [`LibraryError`] for more details.
570    #[error(transparent)]
571    LibraryError(#[from] LibraryError),
572    /// Not all proposals in the Commit were found locally.
573    #[error("Not all proposals in the Commit were found locally.")]
574    ProposalNotFound,
575    /// Update proposal from external sender.
576    #[error("Update proposal from external sender.")]
577    UpdateFromExternalSender,
578    /// SelfRemove proposal from a non-Member.
579    #[error("SelfRemove proposal from a non-Member.")]
580    SelfRemoveFromNonMember,
581}
582
583/// Errors that can arise when creating a [`ProposalQueue`] from committed
584/// proposals.
585#[derive(Error, Debug, PartialEq, Clone)]
586pub(crate) enum FromCommittedProposalsError {
587    /// See [`LibraryError`] for more details.
588    #[error(transparent)]
589    LibraryError(#[from] LibraryError),
590    /// Not all proposals in the Commit were found locally.
591    #[error("Not all proposals in the Commit were found locally.")]
592    ProposalNotFound,
593    /// The sender of a Commit tried to remove themselves.
594    #[error("The sender of a Commit tried to remove themselves.")]
595    SelfRemoval,
596    /// Commit contains two PSK proposals with the same PSK ID.
597    #[error("Commit contains two PSK proposals the PSK ID {0:?}.")]
598    DuplicatePskId(PreSharedKeyId),
599}
600
601/// Create group context ext proposal error
602#[derive(Error, Debug, PartialEq, Clone)]
603pub enum CreateGroupContextExtProposalError<StorageError> {
604    /// See [`LibraryError`] for more details.
605    #[error(transparent)]
606    LibraryError(#[from] LibraryError),
607    /// See [`KeyPackageExtensionSupportError`] for more details.
608    #[error(transparent)]
609    KeyPackageExtensionSupport(#[from] KeyPackageExtensionSupportError),
610    /// See [`ExtensionError`] for more details.
611    #[error(transparent)]
612    Extension(#[from] ExtensionError),
613    /// See [`LeafNodeValidationError`] for more details.
614    #[error(transparent)]
615    LeafNodeValidation(#[from] LeafNodeValidationError),
616    /// See [`MlsGroupStateError`] for more details.
617    #[error(transparent)]
618    MlsGroupStateError(#[from] MlsGroupStateError),
619    /// See [`CreateCommitError`] for more details.
620    #[error(transparent)]
621    CreateCommitError(#[from] CreateCommitError),
622    /// See [`CommitBuilderStageError`] for more details.
623    #[error(transparent)]
624    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
625    /// Error writing updated group to storage.
626    #[error("Error writing updated group data to storage.")]
627    StorageError(StorageError),
628    /// Error validating the extensions
629    #[error(transparent)]
630    InvalidExtensionError(#[from] InvalidExtensionError),
631}
632
633/// Error merging a commit.
634#[derive(Error, Debug, PartialEq, Clone)]
635pub enum MergeCommitError<StorageError> {
636    /// See [`LibraryError`] for more details.
637    #[error(transparent)]
638    LibraryError(#[from] LibraryError),
639    /// Error writing updated group to storage.
640    #[error("Error writing updated group data to storage.")]
641    StorageError(StorageError),
642}
643
644#[cfg(feature = "extensions-draft-08")]
645/// Error validating an AppDataUpdate proposal.
646#[derive(Error, Debug, PartialEq, Clone)]
647pub enum AppDataUpdateValidationError {
648    /// [`AppDataUpdateProposal`](crate::messages::proposals::AppDataUpdateProposal)s
649    /// occur before
650    /// [`GroupContextExtensionsProposal`](crate::messages::proposals::GroupContextExtensionProposal)s.
651    #[error("AppDataUpdate proposals occur before GroupContextExtensions proposals.")]
652    IncorrectOrder,
653    /// Attempted to update the [`AppDataDictionary`](crate::extensions::AppDataDictionary)
654    /// in the
655    /// [`GroupContextExtensionsProposal`](crate::messages::proposals::GroupContextExtensionProposal) directly.
656    #[error("Attempted to update the AppDataDictionary in the GroupContextExtensions proposal directly.")]
657    CannotUpdateDictionaryDirectly,
658    /// More than one [`AppDataUpdate]` proposal per [`ComponentId`] had a Remove operation.
659    ///
660    /// [`ComponentId`]: crate::component::ComponentId
661    #[error("More than one AppDataUpdate proposal per ComponentId had a Remove operation.")]
662    MoreThanOneRemovePerComponentId,
663    /// Proposals for a [`ComponentId`] had both Remove and Update operations.
664    ///
665    /// [`ComponentId`]: crate::component::ComponentId
666    #[error("Proposals for a ComponentId had both Remove and Update operations.")]
667    CombinedRemoveAndUpdateOperations,
668    /// Proposals for a [`ComponentId`] had a Remove for a nonexistent component.
669    ///
670    /// [`ComponentId`]: crate::component::ComponentId
671    #[error("Proposals for a ComponentId had a Remove for a nonexistent component.")]
672    CannotRemoveNonexistentComponent,
673}
674
675/// Error validation a GroupContextExtensions proposal.
676#[derive(Error, Debug, PartialEq, Clone)]
677pub enum GroupContextExtensionsProposalValidationError {
678    /// Commit has more than one GroupContextExtensions proposal.
679    #[error("Commit has more than one GroupContextExtensions proposal.")]
680    TooManyGCEProposals,
681
682    /// See [`LibraryError`] for more details.
683    #[error(transparent)]
684    LibraryError(#[from] LibraryError),
685
686    /// The new extension types in required capabilties contails extensions that are not supported by all group members.
687    #[error(
688        "The new required capabilties contain extension types that are not supported by all group members."
689    )]
690    ExtensionNotSupportedByAllMembers,
691    /// Proposal changes the immutable metadata extension, which is not allowed.
692    #[error("Proposal changes the immutable metadata extension, which is not allowed.")]
693    ChangedImmutableMetadata,
694
695    /// The new extension types in required capabilties contails extensions that are not supported by all group members.
696    #[error(
697        "The new required capabilties contain extension types that are not supported by all group members."
698    )]
699    RequiredExtensionNotSupportedByAllMembers,
700
701    /// An extension in the group context extensions is not listed in the required capabilties'
702    /// extension types.
703    #[error(
704        "An extension in the group context extensions is not listed in the required capabilties' extension types."
705    )]
706    ExtensionNotInRequiredCapabilities,
707
708    /// An extension with a type that is not valid in the group context
709    #[error("Expected valid `Extension` for `GroupContextExtension`, got `{wrong:?}`")]
710    InvalidExtensionTypeError {
711        /// found invalid type
712        wrong: ExtensionType,
713    },
714}