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