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