Skip to main content

openmls/group/mls_group/
errors.rs

1//! # MlsGroup errors
2//!
3//! This module defines the public errors that can be returned from all calls
4//! to methods of [`MlsGroup`](super::MlsGroup).
5
6// These errors are exposed through `crate::group::errors`.
7
8use openmls_traits::types::Ciphersuite;
9use thiserror::Error;
10
11use crate::{
12    error::LibraryError,
13    extensions::errors::InvalidExtensionError,
14    group::{
15        errors::{
16            CreateAddProposalError, CreateCommitError, MergeCommitError, StageCommitError,
17            ValidationError,
18        },
19        CommitBuilderStageError, CreateGroupContextExtProposalError,
20    },
21    schedule::errors::PskError,
22    treesync::{
23        errors::{LeafNodeValidationError, PublicTreeError},
24        node::leaf_node::LeafNodeUpdateError,
25    },
26};
27
28#[cfg(feature = "extensions-draft")]
29pub use crate::schedule::application_export_tree::ApplicationExportTreeError;
30
31#[cfg(doc)]
32use crate::group::GroupId;
33
34/// New group error
35#[derive(Error, Debug, PartialEq, Clone)]
36pub enum NewGroupError<StorageError> {
37    /// See [`LibraryError`] for more details.
38    #[error(transparent)]
39    LibraryError(#[from] LibraryError),
40    /// No matching KeyPackage was found in the key store.
41    #[error("No matching KeyPackage was found in the key store.")]
42    NoMatchingKeyPackage,
43    /// Error accessing the storage.
44    #[error("Error accessing the storage.")]
45    StorageError(StorageError),
46    /// Unsupported proposal type in required capabilities.
47    #[error("Unsupported proposal type in required capabilities.")]
48    UnsupportedProposalType,
49    /// Unsupported extension type in required capabilities.
50    #[error("Unsupported extension type in required capabilities.")]
51    UnsupportedExtensionType,
52    /// Invalid extensions set in configuration
53    #[error("Invalid extensions set in configuration")]
54    InvalidExtensions(#[from] InvalidExtensionError),
55    /// A group with the given [`GroupId`] already exists.
56    #[error("A group with the given GroupId already exists.")]
57    GroupAlreadyExists,
58    /// The ciphersuite is not supported by the crypto provider.
59    #[error("Ciphersuite {0:?} is not supported by the crypto provider.")]
60    UnsupportedCiphersuite(Ciphersuite),
61    /// A virtual-clients processing error occurred.
62    #[cfg(feature = "virtual-clients-draft")]
63    #[error(transparent)]
64    VirtualClientsError(#[from] crate::components::vc_derivation_info::VirtualClientsError),
65}
66
67/// An error when deleting past epoch secrets.
68#[derive(Error, Debug, PartialEq, Eq, Clone)]
69pub enum DeletePastEpochSecretsError<StorageError> {
70    /// Error accessing the storage.
71    #[error(transparent)]
72    StorageError(#[from] StorageError),
73}
74
75/// An error when setting the past epoch deletion policy.
76#[derive(Error, Debug, PartialEq, Eq, Clone)]
77pub enum SetPastEpochDeletionPolicyError<StorageError> {
78    /// Error accessing the storage.
79    #[error(transparent)]
80    StorageError(#[from] StorageError),
81}
82
83/// EmptyInput error
84#[derive(Error, Debug, PartialEq, Eq, Clone)]
85pub enum EmptyInputError {
86    /// An empty list of KeyPackages was provided.
87    #[error("An empty list of KeyPackages was provided.")]
88    AddMembers,
89    /// An empty list of KeyPackage references was provided.
90    #[error("An empty list of KeyPackage references was provided.")]
91    RemoveMembers,
92}
93
94/// Group state error
95#[derive(Error, Debug, PartialEq, Clone)]
96pub enum MlsGroupStateError {
97    /// See [`LibraryError`] for more details.
98    #[error(transparent)]
99    LibraryError(#[from] LibraryError),
100    /// Tried to use a group after being evicted from it.
101    #[error("Tried to use a group after being evicted from it.")]
102    UseAfterEviction,
103    /// Can't create message because a pending proposal exists.
104    #[error("Can't create message because a pending proposal exists.")]
105    PendingProposal,
106    /// Can't execute operation because a pending commit exists.
107    #[error("Can't execute operation because a pending commit exists.")]
108    PendingCommit,
109    /// Can't execute operation because there is no pending commit.
110    #[error("Can't execute operation because there is no pending commit")]
111    NoPendingCommit,
112    /// Requested pending proposal hasn't been found in local pending proposals
113    #[error("Requested pending proposal hasn't been found in local pending proposals.")]
114    PendingProposalNotFound,
115}
116
117/// Error merging pending commit
118#[derive(Error, Debug, PartialEq, Clone)]
119pub enum MergePendingCommitError<StorageError> {
120    /// See [`MlsGroupStateError`] for more details.
121    #[error(transparent)]
122    MlsGroupStateError(#[from] MlsGroupStateError),
123    /// See [`MergeCommitError`] for more details.
124    #[error(transparent)]
125    MergeCommitError(#[from] MergeCommitError<StorageError>),
126}
127
128/// Process message error
129#[derive(Error, Debug, PartialEq, Clone)]
130pub enum PublicProcessMessageError {
131    /// See [`LibraryError`] for more details.
132    #[error(transparent)]
133    LibraryError(#[from] LibraryError),
134    /// The message's wire format is incompatible with the group's wire format policy.
135    #[error("The message's wire format is incompatible with the group's wire format policy.")]
136    IncompatibleWireFormat,
137    /// See [`ValidationError`] for more details.
138    #[error(transparent)]
139    ValidationError(#[from] ValidationError),
140    /// See [`StageCommitError`] for more details.
141    #[error(transparent)]
142    InvalidCommit(#[from] StageCommitError),
143    /// External application messages are not permitted.
144    #[error("External application messages are not permitted.")]
145    UnauthorizedExternalApplicationMessage,
146    /// External commit messages are not permitted.
147    #[error("Commit messages from external senders are not permitted.")]
148    UnauthorizedExternalCommitMessage,
149    /// The proposal is invalid for the Sender of type [External](crate::prelude::Sender::External)
150    #[error("The proposal is invalid for the Sender of type External")]
151    UnsupportedProposalType,
152
153    /// The group's GroupContext requires Safe AAD framing, but the message's
154    /// `authenticated_data` did not start with a well-formed `SafeAad`.
155    #[cfg(feature = "extensions-draft")]
156    #[error("malformed SafeAAD prefix in authenticated_data")]
157    MalformedSafeAad,
158}
159
160/// Process message error
161#[derive(Error, Debug, PartialEq, Clone)]
162pub enum ProcessMessageError<StorageError> {
163    /// See [`LibraryError`] for more details.
164    #[error(transparent)]
165    LibraryError(#[from] LibraryError),
166    /// Error writing to storage.
167    #[error("Error writing to storage: {0}")]
168    StorageError(StorageError),
169    /// The message's wire format is incompatible with the group's wire format policy.
170    #[error("The message's wire format is incompatible with the group's wire format policy.")]
171    IncompatibleWireFormat,
172    /// See [`ValidationError`] for more details.
173    #[error(transparent)]
174    ValidationError(#[from] ValidationError),
175    /// See [`MlsGroupStateError`] for more details.
176    #[error(transparent)]
177    GroupStateError(#[from] MlsGroupStateError),
178    /// See [`StageCommitError`] for more details.
179    #[error(transparent)]
180    InvalidCommit(#[from] StageCommitError),
181    /// External application messages are not permitted.
182    #[error("External application messages are not permitted.")]
183    UnauthorizedExternalApplicationMessage,
184    /// External commit messages are not permitted.
185    #[error("Commit messages from external senders are not permitted.")]
186    UnauthorizedExternalCommitMessage,
187    /// The proposal is invalid for the Sender of type [External](crate::prelude::Sender::External)
188    #[error("The proposal is invalid for the Sender of type External")]
189    UnsupportedProposalType,
190    /// The group's GroupContext requires Safe AAD framing, but the message's
191    /// `authenticated_data` did not start with a well-formed `SafeAad`.
192    #[cfg(feature = "extensions-draft")]
193    #[error("malformed SafeAAD prefix in authenticated_data")]
194    MalformedSafeAad,
195}
196
197/// Create message error
198#[cfg(not(feature = "virtual-clients-draft"))]
199#[derive(Error, Debug, PartialEq, Clone)]
200pub enum CreateMessageError {
201    /// See [`LibraryError`] for more details.
202    #[error(transparent)]
203    LibraryError(#[from] LibraryError),
204    /// See [`MlsGroupStateError`] for more details.
205    #[error(transparent)]
206    GroupStateError(#[from] MlsGroupStateError),
207}
208
209/// Add members error
210#[derive(Error, Debug, PartialEq, Clone)]
211pub enum AddMembersError<StorageError> {
212    /// See [`LibraryError`] for more details.
213    #[error(transparent)]
214    LibraryError(#[from] LibraryError),
215    /// See [`EmptyInputError`] for more details.
216    #[error(transparent)]
217    EmptyInput(#[from] EmptyInputError),
218    /// See [`CreateCommitError`] for more details.
219    #[error(transparent)]
220    CreateCommitError(#[from] CreateCommitError),
221    /// See [`CommitBuilderStageError`] for more details.
222    #[error(transparent)]
223    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
224    /// See [`MlsGroupStateError`] for more details.
225    #[error(transparent)]
226    GroupStateError(#[from] MlsGroupStateError),
227    /// Error writing to storage.
228    #[error("Error writing to storage")]
229    StorageError(StorageError),
230}
231
232/// Add members error
233#[derive(Error, Debug, PartialEq, Clone)]
234pub enum SwapMembersError<StorageError> {
235    /// Unable to map the key packages to the given leaf indices.
236    #[error("Number of added and removed members is not the same")]
237    InvalidInput,
238
239    /// See [`EmptyInputError`] for more details.
240    #[error(transparent)]
241    EmptyInput(#[from] EmptyInputError),
242
243    /// See [`MlsGroupStateError`] for more details.
244    #[error(transparent)]
245    GroupStateError(#[from] MlsGroupStateError),
246
247    /// See [`LibraryError`] for more details.
248    #[error(transparent)]
249    LibraryError(#[from] LibraryError),
250
251    /// The member that should be removed can not be found.
252    #[error("The member that should be removed can not be found.")]
253    UnknownMember,
254
255    /// Error writing to storage
256    #[error("Error writing to storage: {0}")]
257    StorageError(StorageError),
258
259    /// See [`CommitBuilderStageError`] for more details.
260    #[error(transparent)]
261    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
262
263    /// See [`CreateCommitError`] for more details.
264    #[error(transparent)]
265    CreateCommitError(#[from] CreateCommitError),
266}
267
268/// Propose add members error
269#[derive(Error, Debug, PartialEq, Clone)]
270pub enum ProposeAddMemberError<StorageError> {
271    /// See [`LibraryError`] for more details.
272    #[error(transparent)]
273    LibraryError(#[from] LibraryError),
274    /// The new member does not support all required extensions.
275    #[error("The new member does not support all required extensions.")]
276    UnsupportedExtensions,
277    /// See [`MlsGroupStateError`] for more details.
278    #[error(transparent)]
279    GroupStateError(#[from] MlsGroupStateError),
280    /// See [`LeafNodeValidationError`] for more details.
281    #[error(transparent)]
282    LeafNodeValidation(#[from] LeafNodeValidationError),
283    /// Error writing to storage
284    #[error("Error writing to storage: {0}")]
285    StorageError(StorageError),
286}
287
288/// Propose remove members error
289#[derive(Error, Debug, PartialEq, Clone)]
290pub enum ProposeRemoveMemberError<StorageError> {
291    /// See [`LibraryError`] for more details.
292    #[error(transparent)]
293    LibraryError(#[from] LibraryError),
294    /// See [`MlsGroupStateError`] for more details.
295    #[error(transparent)]
296    GroupStateError(#[from] MlsGroupStateError),
297    /// The member that should be removed can not be found.
298    #[error("The member that should be removed can not be found.")]
299    UnknownMember,
300    /// Error writing to storage
301    #[error("Error writing to storage: {0}")]
302    StorageError(StorageError),
303}
304
305/// Remove members error
306#[derive(Error, Debug, PartialEq, Clone)]
307pub enum RemoveMembersError<StorageError> {
308    /// See [`LibraryError`] for more details.
309    #[error(transparent)]
310    LibraryError(#[from] LibraryError),
311    /// See [`EmptyInputError`] for more details.
312    #[error(transparent)]
313    EmptyInput(#[from] EmptyInputError),
314    /// See [`CreateCommitError`] for more details.
315    #[error(transparent)]
316    CreateCommitError(#[from] CreateCommitError),
317    /// See [`CommitBuilderStageError`] for more details.
318    #[error(transparent)]
319    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
320    /// See [`MlsGroupStateError`] for more details.
321    #[error(transparent)]
322    GroupStateError(#[from] MlsGroupStateError),
323    /// The member that should be removed can not be found.
324    #[error("The member that should be removed can not be found.")]
325    UnknownMember,
326    /// Error writing to storage
327    #[error("Error writing to storage: {0}")]
328    StorageError(StorageError),
329}
330
331/// Leave group error
332#[derive(Error, Debug, PartialEq, Clone)]
333pub enum LeaveGroupError<StorageError> {
334    /// See [`LibraryError`] for more details.
335    #[error(transparent)]
336    LibraryError(#[from] LibraryError),
337    /// See [`MlsGroupStateError`] for more details.
338    #[error(transparent)]
339    GroupStateError(#[from] MlsGroupStateError),
340    /// An error ocurred while writing to storage
341    #[error("An error ocurred while writing to storage")]
342    StorageError(StorageError),
343    /// SelfRemove not allowed with pure ciphertext outgoing wire format policy.
344    #[error("SelfRemove not allowed with pure ciphertext outgoing wire format policy.")]
345    CannotSelfRemoveWithPureCiphertext,
346}
347
348/// Self update error
349#[derive(Error, Debug, PartialEq, Clone)]
350pub enum SelfUpdateError<StorageError> {
351    /// See [`LibraryError`] for more details.
352    #[error(transparent)]
353    LibraryError(#[from] LibraryError),
354    /// See [`CreateCommitError`] for more details.
355    #[error(transparent)]
356    CreateCommitError(#[from] CreateCommitError),
357    /// See [`CommitBuilderStageError`] for more details.
358    #[error(transparent)]
359    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
360    /// See [`MlsGroupStateError`] for more details.
361    #[error(transparent)]
362    GroupStateError(#[from] MlsGroupStateError),
363    /// Error accessing the storage.
364    #[error("Error accessing the storage.")]
365    StorageError(StorageError),
366    /// Virtual-clients error.
367    #[cfg(feature = "virtual-clients-draft")]
368    #[error(transparent)]
369    VirtualClientsError(#[from] crate::components::vc_derivation_info::VirtualClientsError),
370}
371
372/// Propose self update error
373#[derive(Error, Debug, PartialEq, Clone)]
374pub enum ProposeSelfUpdateError<StorageError> {
375    /// See [`LibraryError`] for more details.
376    #[error(transparent)]
377    LibraryError(#[from] LibraryError),
378
379    /// See [`MlsGroupStateError`] for more details.
380    #[error(transparent)]
381    GroupStateError(#[from] MlsGroupStateError),
382    /// Error accessing storage.
383    #[error("Error accessing storage.")]
384    StorageError(StorageError),
385    /// See [`PublicTreeError`] for more details.
386    #[error(transparent)]
387    PublicTreeError(#[from] PublicTreeError),
388    /// See [`LeafNodeUpdateError`] for more details.
389    #[error(transparent)]
390    LeafNodeUpdateError(#[from] LeafNodeUpdateError<StorageError>),
391    /// The updated leaf node does not support all group context extensions.
392    #[error("The updated leaf node does not support all group context extensions.")]
393    UnsupportedGroupContextExtensions,
394    /// The `leaf_node_parameters.credential_with_key` does not match
395    /// `new_signer.credential_with_key` (rotation paths only).
396    #[error("Mismatched credential_with_key between leaf_node_parameters and new_signer")]
397    InvalidLeafNodeParameters,
398    /// The `leaf_node_parameters.credential_with_key` does not match
399    /// `new_signer.credential_with_key` (rotation paths only).
400    #[error("Mismatched ciphersuite between new_signer and the group")]
401    InvalidSignerCiphersuite,
402}
403
404/// Commit to pending proposals error
405#[derive(Error, Debug, PartialEq, Clone)]
406pub enum CommitToPendingProposalsError<StorageError> {
407    /// See [`LibraryError`] for more details.
408    #[error(transparent)]
409    LibraryError(#[from] LibraryError),
410    /// See [`CreateCommitError`] for more details.
411    #[error(transparent)]
412    CreateCommitError(#[from] CreateCommitError),
413    /// See [`CommitBuilderStageError`] for more details.
414    #[error(transparent)]
415    CommitBuilderStageError(#[from] CommitBuilderStageError<StorageError>),
416    /// See [`MlsGroupStateError`] for more details.
417    #[error(transparent)]
418    GroupStateError(#[from] MlsGroupStateError),
419    /// Error writing to storage
420    #[error("Error writing to storage: {0}")]
421    StorageError(StorageError),
422}
423
424/// Errors that can happen when exporting a group info object.
425#[derive(Error, Debug, PartialEq, Clone)]
426pub enum ExportGroupInfoError {
427    /// See [`LibraryError`] for more details.
428    #[error(transparent)]
429    LibraryError(#[from] LibraryError),
430    /// See [`MlsGroupStateError`] for more details.
431    #[error(transparent)]
432    GroupStateError(#[from] MlsGroupStateError),
433    /// See [`InvalidExtensionError`] for more details.
434    #[error(transparent)]
435    InvalidExtensionError(#[from] InvalidExtensionError),
436}
437
438/// Export secret error
439#[cfg(feature = "extensions-draft")]
440#[derive(Error, Debug, PartialEq, Clone)]
441pub enum SafeExportSecretError<StorageError> {
442    /// See [`MlsGroupStateError`] for more details.
443    #[error(transparent)]
444    GroupState(#[from] MlsGroupStateError),
445    /// See [`ApplicationExportTreeError`] for more details.
446    #[error(transparent)]
447    ApplicationExportTree(#[from] ApplicationExportTreeError),
448    /// Group doesn't support application exports.
449    #[error("Group doesn't support application exports.")]
450    Unsupported,
451    /// Storage error
452    #[error("Error accessing storage: {0}")]
453    Storage(StorageError),
454}
455
456/// Error resolving a processed message carrying an unresolved app data commit.
457#[cfg(feature = "extensions-draft")]
458#[derive(Error, Debug, PartialEq, Clone)]
459pub enum ResolveAppDataCommitError {
460    /// The processed message does not carry an unresolved app data commit.
461    #[error("The processed message does not carry an unresolved app data commit.")]
462    NotAnUnresolvedAppDataCommit,
463    /// See [`StageCommitError`] for more details.
464    #[error(transparent)]
465    StageCommit(#[from] StageCommitError),
466}
467
468/// Export secret error
469#[cfg(feature = "extensions-draft")]
470#[derive(Error, Debug, PartialEq, Clone)]
471pub enum ProcessedMessageSafeExportSecretError {
472    /// See [`StagedSafeExportSecretError`] for more details.
473    #[error(transparent)]
474    SafeExportSecretError(#[from] StagedSafeExportSecretError),
475    /// Processed message is not a commit.
476    #[error("Processed message is not a commit.")]
477    NotACommit,
478}
479
480/// Export secret error
481#[cfg(feature = "extensions-draft")]
482#[derive(Error, Debug, PartialEq, Clone)]
483pub enum PendingSafeExportSecretError<StorageError> {
484    /// See [`StagedSafeExportSecretError`] for more details.
485    #[error(transparent)]
486    SafeExportSecretError(#[from] StagedSafeExportSecretError),
487    /// No pending commit.
488    #[error("No pending commit.")]
489    NoPendingCommit,
490    /// Storage error
491    #[error("Error accessing storage: {0}")]
492    Storage(StorageError),
493    /// Only group members can export secrets.
494    #[error("Only group members can export secrets.")]
495    NotGroupMember,
496}
497
498/// Export secret from a pending commit
499#[cfg(feature = "extensions-draft")]
500#[derive(Error, Debug, PartialEq, Clone)]
501pub enum StagedSafeExportSecretError {
502    /// Only group members can export secrets.
503    #[error("Only group members can export secrets.")]
504    NotGroupMember,
505    /// See [`ApplicationExportTreeError`] for more details.
506    #[error(transparent)]
507    ApplicationExportTree(#[from] ApplicationExportTreeError),
508    /// Group doesn't support application exports.
509    #[error("Group doesn't support application exports.")]
510    Unsupported,
511}
512
513/// Export secret error
514#[derive(Error, Debug, PartialEq, Clone)]
515pub enum ExportSecretError {
516    /// See [`LibraryError`] for more details.
517    #[error(transparent)]
518    LibraryError(#[from] LibraryError),
519    /// The requested key length is too long.
520    #[error("The requested key length is too long.")]
521    KeyLengthTooLong,
522    /// See [`MlsGroupStateError`] for more details.
523    #[error(transparent)]
524    GroupStateError(#[from] MlsGroupStateError),
525}
526
527/// Propose PSK error
528#[derive(Error, Debug, PartialEq, Clone)]
529pub enum ProposePskError {
530    /// See [`PskError`] for more details.
531    #[error(transparent)]
532    Psk(#[from] PskError),
533    /// See [`MlsGroupStateError`] for more details.
534    #[error(transparent)]
535    GroupStateError(#[from] MlsGroupStateError),
536    /// See [`LibraryError`] for more details.
537    #[error(transparent)]
538    LibraryError(#[from] LibraryError),
539}
540
541/// Proposal error
542#[derive(Error, Debug, PartialEq, Clone)]
543pub enum ProposalError<StorageError> {
544    /// See [`LibraryError`] for more details.
545    #[error(transparent)]
546    LibraryError(#[from] LibraryError),
547    /// See [`ProposeAddMemberError`] for more details.
548    #[error(transparent)]
549    ProposeAddMemberError(#[from] ProposeAddMemberError<StorageError>),
550    /// See [`CreateAddProposalError`] for more details.
551    #[error(transparent)]
552    CreateAddProposalError(#[from] CreateAddProposalError),
553    /// See [`ProposeSelfUpdateError`] for more details.
554    #[error(transparent)]
555    ProposeSelfUpdateError(#[from] ProposeSelfUpdateError<StorageError>),
556    /// See [`ProposeRemoveMemberError`] for more details.
557    #[error(transparent)]
558    ProposeRemoveMemberError(#[from] ProposeRemoveMemberError<StorageError>),
559    /// See [`MlsGroupStateError`] for more details.
560    #[error(transparent)]
561    GroupStateError(#[from] MlsGroupStateError),
562    /// See [`ValidationError`] for more details.
563    #[error(transparent)]
564    ValidationError(#[from] ValidationError),
565    /// See [`CreateGroupContextExtProposalError`] for more details.
566    #[error(transparent)]
567    CreateGroupContextExtProposalError(#[from] CreateGroupContextExtProposalError<StorageError>),
568    /// See [`InvalidExtensionError`]
569    #[error(transparent)]
570    InvalidExtension(#[from] InvalidExtensionError),
571    /// Error writing proposal to storage.
572    #[error("error writing proposal to storage")]
573    StorageError(StorageError),
574}
575
576/// Remove proposal error
577#[derive(Error, Debug, PartialEq, Clone)]
578pub enum RemoveProposalError<StorageError> {
579    /// Couldn't find the proposal for the given `ProposalRef`.
580    #[error("Couldn't find the proposal for the given `ProposalRef`")]
581    ProposalNotFound,
582    /// Error erasing proposal from storage.
583    #[error("error writing proposal to storage")]
584    Storage(StorageError),
585}
586
587#[cfg(feature = "virtual-clients-draft")]
588pub use virtual_clients_draft::*;
589
590#[cfg(feature = "virtual-clients-draft")]
591mod virtual_clients_draft {
592    use thiserror::Error;
593
594    use super::MlsGroupStateError;
595    use crate::error::LibraryError;
596    use crate::framing::MessageEncryptionError;
597    use crate::group::SafeExportSecretError;
598    use crate::tree::secret_tree::SecretTreeError;
599
600    /// Create message error
601    #[derive(Error, Debug, PartialEq, Clone)]
602    pub enum CreateMessageError<StorageError> {
603        /// See [`LibraryError`] for more details.
604        #[error(transparent)]
605        LibraryError(#[from] LibraryError),
606        /// See [`MlsGroupStateError`] for more details.
607        #[error(transparent)]
608        GroupStateError(#[from] MlsGroupStateError),
609        /// See [`MessageEncryptionError`] for more details.
610        #[error(transparent)]
611        MessageEncryptionError(#[from] MessageEncryptionError<StorageError>),
612        /// Error writing to storage.
613        #[error("Error writing to storage: {0}")]
614        StorageError(StorageError),
615    }
616
617    /// Confirm message error
618    #[derive(Error, Debug, PartialEq, Clone)]
619    pub enum ConfirmMessageError<StorageError> {
620        /// See [`SecretTreeError`] for more details.
621        #[error(transparent)]
622        SecretTreeError(#[from] SecretTreeError),
623        /// The requested epoch is newer than the group's current epoch.
624        #[error("The requested epoch is newer than the group's current epoch.")]
625        FutureEpoch,
626        /// Error writing to storage.
627        #[error("Error writing to storage: {0}")]
628        StorageError(StorageError),
629    }
630
631    impl<StorageError> From<ConfirmMessageError<StorageError>> for CreateMessageError<StorageError> {
632        fn from(err: ConfirmMessageError<StorageError>) -> Self {
633            match err {
634                ConfirmMessageError::SecretTreeError(e) => {
635                    CreateMessageError::MessageEncryptionError(
636                        MessageEncryptionError::SecretTreeError(e),
637                    )
638                }
639                // Unreachable: `create_message` confirms at the current epoch,
640                // which never triggers the future-epoch guard.
641                ConfirmMessageError::FutureEpoch => CreateMessageError::LibraryError(
642                    LibraryError::custom("confirm_application_message reported a future epoch"),
643                ),
644                ConfirmMessageError::StorageError(e) => CreateMessageError::StorageError(e),
645            }
646        }
647    }
648
649    /// Errors returned by
650    /// [`MlsGroup::register_vc_emulation_epoch`](crate::group::MlsGroup::register_vc_emulation_epoch).
651    #[derive(Error, Debug, PartialEq, Clone)]
652    pub enum RegisterVcEmulationEpochError<StorageError> {
653        /// See [`SafeExportSecretError`] for more details.
654        #[error(transparent)]
655        SafeExportSecret(#[from] SafeExportSecretError<StorageError>),
656        /// See [`VirtualClientsError`](crate::components::vc_derivation_info::VirtualClientsError)
657        /// for more details.
658        #[error(transparent)]
659        VirtualClients(#[from] crate::components::vc_derivation_info::VirtualClientsError),
660        /// Persisting the derived virtual-clients state to storage failed.
661        #[error("Error writing virtual-clients state to storage")]
662        Storage(StorageError),
663    }
664}