Skip to main content

crypto_core/
error.rs

1// SPDX-FileCopyrightText: Copyright © 2026 ReallyMe LLC. All rights reserved
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use thiserror::Error;
6
7/// Backend implementation that performed an AEAD operation.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum AeadBackend {
10    /// Pure-Rust native backend.
11    Native,
12    /// Swift/Apple platform backend.
13    Swift,
14    /// WebAssembly backend.
15    Wasm,
16    /// Kotlin/Android platform backend.
17    Kotlin,
18}
19
20impl core::fmt::Display for AeadBackend {
21    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22        let name = match self {
23            AeadBackend::Native => "native",
24            AeadBackend::Swift => "swift",
25            AeadBackend::Wasm => "wasm",
26            AeadBackend::Kotlin => "kotlin",
27        };
28        write!(f, "{name}")
29    }
30}
31
32/// Specific reason an AEAD encrypt or decrypt operation failed.
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum AeadFailureKind {
35    /// The supplied key material was not valid for the cipher.
36    InvalidKeyMaterial,
37    /// An input length exceeded the representable range.
38    LengthOverflow,
39    /// The ciphertext was shorter than the authentication tag.
40    ShortCiphertext,
41    /// The backend returned an output of unexpected length.
42    InvalidOutputLength,
43    /// Tag verification failed (ciphertext or AAD tampered/wrong key).
44    AuthenticationFailed,
45    /// The backend reported an unspecified internal failure.
46    BackendFailure,
47}
48
49impl core::fmt::Display for AeadFailureKind {
50    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
51        let detail = match self {
52            AeadFailureKind::InvalidKeyMaterial => "invalid key material",
53            AeadFailureKind::LengthOverflow => "length overflow",
54            AeadFailureKind::ShortCiphertext => "ciphertext shorter than tag",
55            AeadFailureKind::InvalidOutputLength => "backend returned invalid output length",
56            AeadFailureKind::AuthenticationFailed => "authentication failed",
57            AeadFailureKind::BackendFailure => "backend failure",
58        };
59        write!(f, "{detail}")
60    }
61}
62
63/// Backend implementation that performed a signature operation.
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub enum SignatureBackend {
66    /// Pure-Rust native backend.
67    Native,
68    /// Swift/Apple platform backend.
69    Swift,
70    /// WebAssembly backend.
71    Wasm,
72    /// Kotlin/Android platform backend.
73    Kotlin,
74    /// Apple Secure Enclave hardware-backed backend.
75    SecureEnclave,
76}
77
78impl core::fmt::Display for SignatureBackend {
79    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
80        let name = match self {
81            SignatureBackend::Native => "native",
82            SignatureBackend::Swift => "swift",
83            SignatureBackend::Wasm => "wasm",
84            SignatureBackend::Kotlin => "kotlin",
85            SignatureBackend::SecureEnclave => "secure_enclave",
86        };
87        write!(f, "{name}")
88    }
89}
90
91/// Signature-related operation being attempted when a failure occurred.
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub enum SignatureOperation {
94    /// Producing a signature over a message.
95    Sign,
96    /// Verifying a signature against a message.
97    Verify,
98    /// Key generation, import, or other key management.
99    KeyManagement,
100}
101
102impl core::fmt::Display for SignatureOperation {
103    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
104        let op = match self {
105            SignatureOperation::Sign => "sign",
106            SignatureOperation::Verify => "verify",
107            SignatureOperation::KeyManagement => "key_management",
108        };
109        write!(f, "{op}")
110    }
111}
112
113/// Specific reason a signature operation failed.
114#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum SignatureFailureKind {
116    /// The backend reported an unspecified internal failure.
117    BackendFailure,
118    /// The supplied private key was malformed or invalid.
119    InvalidPrivateKey,
120    /// The supplied public key was malformed or invalid.
121    InvalidPublicKey,
122    /// The signature was malformed or failed verification.
123    InvalidSignature,
124    /// The message input was invalid for the operation.
125    InvalidMessage,
126    /// Key generation did not succeed.
127    KeyGenerationFailed,
128    /// The Secure Enclave was not available on this device.
129    SecureEnclaveUnavailable,
130    /// The Secure Enclave rejected the supplied key.
131    SecureEnclaveRejectedKey,
132}
133
134impl core::fmt::Display for SignatureFailureKind {
135    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
136        let detail = match self {
137            SignatureFailureKind::BackendFailure => "backend failure",
138            SignatureFailureKind::InvalidPrivateKey => "invalid private key",
139            SignatureFailureKind::InvalidPublicKey => "invalid public key",
140            SignatureFailureKind::InvalidSignature => "invalid signature",
141            SignatureFailureKind::InvalidMessage => "invalid message",
142            SignatureFailureKind::KeyGenerationFailed => "key generation failed",
143            SignatureFailureKind::SecureEnclaveUnavailable => "secure enclave unavailable",
144            SignatureFailureKind::SecureEnclaveRejectedKey => "secure enclave rejected key",
145        };
146        write!(f, "{detail}")
147    }
148}
149
150/// Specific reason a key agreement operation failed.
151#[derive(Debug, Clone, Copy, PartialEq, Eq)]
152pub enum KeyAgreementFailureKind {
153    /// Deriving the shared secret did not succeed.
154    DeriveSharedSecretFailed,
155    /// Key generation did not succeed.
156    KeyGenerationFailed,
157}
158
159impl core::fmt::Display for KeyAgreementFailureKind {
160    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
161        let detail = match self {
162            KeyAgreementFailureKind::DeriveSharedSecretFailed => "derive shared secret failed",
163            KeyAgreementFailureKind::KeyGenerationFailed => "key generation failed",
164        };
165        write!(f, "{detail}")
166    }
167}
168
169/// Specific reason a KEM (key encapsulation) operation failed.
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub enum KemFailureKind {
172    /// Key generation did not succeed.
173    KeyGenerationFailed,
174    /// Encapsulation did not succeed.
175    EncapsulateFailed,
176    /// Decapsulation did not succeed.
177    DecapsulateFailed,
178}
179
180impl core::fmt::Display for KemFailureKind {
181    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
182        let detail = match self {
183            KemFailureKind::KeyGenerationFailed => "key generation failed",
184            KemFailureKind::EncapsulateFailed => "encapsulate failed",
185            KemFailureKind::DecapsulateFailed => "decapsulate failed",
186        };
187        write!(f, "{detail}")
188    }
189}
190
191/// Key-wrapping algorithm identifier.
192#[derive(Debug, Clone, Copy, PartialEq, Eq)]
193pub enum KeyWrapAlgorithm {
194    /// AES-256 Key Wrap as specified by RFC 3394 / NIST SP 800-38F.
195    Aes256Kw,
196}
197
198impl core::fmt::Display for KeyWrapAlgorithm {
199    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
200        let detail = match self {
201            KeyWrapAlgorithm::Aes256Kw => "AES-256-KW",
202        };
203        write!(f, "{detail}")
204    }
205}
206
207/// Key-wrap operation being attempted when a failure occurred.
208#[derive(Debug, Clone, Copy, PartialEq, Eq)]
209pub enum KeyWrapOperation {
210    /// Wrapping plaintext key material.
211    Wrap,
212    /// Unwrapping wrapped key material.
213    Unwrap,
214}
215
216impl core::fmt::Display for KeyWrapOperation {
217    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
218        let op = match self {
219            KeyWrapOperation::Wrap => "wrap",
220            KeyWrapOperation::Unwrap => "unwrap",
221        };
222        write!(f, "{op}")
223    }
224}
225
226/// Specific reason a key-wrap operation failed.
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
228pub enum KeyWrapFailureKind {
229    /// The key-encryption key did not have the required length.
230    InvalidKekLength,
231    /// Plaintext key material was too short for RFC 3394 AES-KW.
232    InvalidPlaintextLength,
233    /// Wrapped key material was too short or malformed for RFC 3394 AES-KW.
234    InvalidWrappedLength,
235    /// An input or output length exceeded the representable range.
236    LengthOverflow,
237    /// The wrapped key integrity check failed.
238    IntegrityCheckFailed,
239    /// The backend reported an unspecified internal failure.
240    BackendFailure,
241}
242
243impl core::fmt::Display for KeyWrapFailureKind {
244    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
245        let detail = match self {
246            KeyWrapFailureKind::InvalidKekLength => "invalid key-encryption key length",
247            KeyWrapFailureKind::InvalidPlaintextLength => "invalid plaintext key length",
248            KeyWrapFailureKind::InvalidWrappedLength => "invalid wrapped key length",
249            KeyWrapFailureKind::LengthOverflow => "length overflow",
250            KeyWrapFailureKind::IntegrityCheckFailed => "integrity check failed",
251            KeyWrapFailureKind::BackendFailure => "backend failure",
252        };
253        write!(f, "{detail}")
254    }
255}
256
257/// Password-based key derivation algorithm identifier.
258#[derive(Debug, Clone, Copy, PartialEq, Eq)]
259pub enum KdfAlgorithm {
260    /// Argon2id memory-hard KDF.
261    Argon2id,
262    /// PBKDF2 password-based KDF for legacy interop.
263    Pbkdf2,
264    /// NIST Concat KDF as profiled by JOSE/JWA ECDH-ES.
265    ConcatKdf,
266}
267
268impl core::fmt::Display for KdfAlgorithm {
269    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
270        let detail = match self {
271            KdfAlgorithm::Argon2id => "Argon2id",
272            KdfAlgorithm::Pbkdf2 => "PBKDF2",
273            KdfAlgorithm::ConcatKdf => "Concat KDF",
274        };
275        write!(f, "{detail}")
276    }
277}
278
279/// Versioned parameter profile for the KDF.
280#[derive(Debug, Clone, Copy, PartialEq, Eq)]
281pub enum KdfProfile {
282    /// Argon2id parameter profile version 1.
283    Argon2idV1,
284    /// Argon2id parameter profile version 2.
285    Argon2idV2,
286    /// PBKDF2 using HMAC-SHA-256 as the PRF.
287    Pbkdf2HmacSha256,
288    /// PBKDF2 using HMAC-SHA-512 as the PRF.
289    Pbkdf2HmacSha512,
290    /// JWA ECDH-ES Concat KDF using SHA-256.
291    JwaEcdhEsSha256,
292}
293
294impl core::fmt::Display for KdfProfile {
295    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
296        let detail = match self {
297            KdfProfile::Argon2idV1 => "Argon2id v1",
298            KdfProfile::Argon2idV2 => "Argon2id v2",
299            KdfProfile::Pbkdf2HmacSha256 => "PBKDF2-HMAC-SHA-256",
300            KdfProfile::Pbkdf2HmacSha512 => "PBKDF2-HMAC-SHA-512",
301            KdfProfile::JwaEcdhEsSha256 => "JWA ECDH-ES Concat KDF SHA-256",
302        };
303        write!(f, "{detail}")
304    }
305}
306
307/// Specific reason a KDF operation failed.
308#[derive(Debug, Clone, Copy, PartialEq, Eq)]
309pub enum KdfFailureKind {
310    /// The secret/password input had an unacceptable length.
311    InvalidSecretLength,
312    /// The salt input had an unacceptable length.
313    InvalidSaltLength,
314    /// The requested output length was unacceptable.
315    InvalidOutputLength,
316    /// The iteration count was zero or outside this API's accepted range.
317    InvalidIterationCount,
318    /// The supplied KDF parameters were invalid.
319    InvalidParams,
320    /// The derivation itself did not succeed.
321    DerivationFailed,
322}
323
324impl core::fmt::Display for KdfFailureKind {
325    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
326        let detail = match self {
327            KdfFailureKind::InvalidSecretLength => "invalid secret length",
328            KdfFailureKind::InvalidSaltLength => "invalid salt length",
329            KdfFailureKind::InvalidOutputLength => "invalid output length",
330            KdfFailureKind::InvalidIterationCount => "invalid iteration count",
331            KdfFailureKind::InvalidParams => "invalid parameters",
332            KdfFailureKind::DerivationFailed => "derivation failed",
333        };
334        write!(f, "{detail}")
335    }
336}
337
338/// Hash function underlying an HKDF operation.
339#[derive(Debug, Clone, Copy, PartialEq, Eq)]
340pub enum HkdfHash {
341    /// HKDF using SHA-2-256.
342    Sha2_256,
343    /// HKDF using SHA-3-256.
344    Sha3_256,
345}
346
347impl core::fmt::Display for HkdfHash {
348    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
349        let detail = match self {
350            HkdfHash::Sha2_256 => "SHA2-256",
351            HkdfHash::Sha3_256 => "SHA3-256",
352        };
353        write!(f, "{detail}")
354    }
355}
356
357/// Specific reason an HKDF operation failed.
358#[derive(Debug, Clone, Copy, PartialEq, Eq)]
359pub enum HkdfFailureKind {
360    /// The input key material had an unacceptable length.
361    InvalidIkmLength,
362    /// The domain-separation tag had an unacceptable length.
363    InvalidDomainTagLength,
364    /// The domain-separation tag contained an invalid byte.
365    InvalidDomainTagByte,
366    /// An input length exceeded the representable range.
367    LengthOverflow,
368    /// The requested output length was unacceptable.
369    InvalidOutputLength,
370    /// The HKDF expand step did not succeed.
371    ExpandFailed,
372}
373
374impl core::fmt::Display for HkdfFailureKind {
375    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
376        let detail = match self {
377            HkdfFailureKind::InvalidIkmLength => "invalid input key material length",
378            HkdfFailureKind::InvalidDomainTagLength => "invalid domain tag length",
379            HkdfFailureKind::InvalidDomainTagByte => "invalid domain tag byte",
380            HkdfFailureKind::LengthOverflow => "length overflow",
381            HkdfFailureKind::InvalidOutputLength => "invalid output length",
382            HkdfFailureKind::ExpandFailed => "expand failed",
383        };
384        write!(f, "{detail}")
385    }
386}
387
388/// Hash function underlying an HMAC operation.
389#[derive(Debug, Clone, Copy, PartialEq, Eq)]
390pub enum MacHash {
391    /// HMAC using SHA-256.
392    Sha2_256,
393    /// HMAC using SHA-512.
394    Sha2_512,
395}
396
397impl core::fmt::Display for MacHash {
398    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
399        let detail = match self {
400            MacHash::Sha2_256 => "SHA-256",
401            MacHash::Sha2_512 => "SHA-512",
402        };
403        write!(f, "{detail}")
404    }
405}
406
407/// Specific reason an HMAC operation failed.
408#[derive(Debug, Clone, Copy, PartialEq, Eq)]
409pub enum MacFailureKind {
410    /// The supplied key was empty or exceeded the accepted size limit.
411    InvalidKeyLength,
412    /// The supplied authentication tag length did not match the algorithm.
413    InvalidTagLength,
414    /// Tag verification failed.
415    VerificationFailed,
416    /// The backend reported an unspecified internal failure.
417    BackendFailure,
418}
419
420impl core::fmt::Display for MacFailureKind {
421    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
422        let detail = match self {
423            MacFailureKind::InvalidKeyLength => "invalid key length",
424            MacFailureKind::InvalidTagLength => "invalid tag length",
425            MacFailureKind::VerificationFailed => "verification failed",
426            MacFailureKind::BackendFailure => "backend failure",
427        };
428        write!(f, "{detail}")
429    }
430}
431
432/// Purpose of the random output being generated.
433#[derive(Debug, Clone, Copy, PartialEq, Eq)]
434pub enum RngOutputKind {
435    /// Generic random bytes with no fixed length.
436    Generic,
437    /// A 12-byte AEAD nonce.
438    AeadNonce12,
439    /// A 16-byte Argon2 salt.
440    Argon2Salt16,
441    /// A 32-byte Argon2 salt.
442    Argon2Salt32,
443}
444
445impl core::fmt::Display for RngOutputKind {
446    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
447        let detail = match self {
448            RngOutputKind::Generic => "random bytes",
449            RngOutputKind::AeadNonce12 => "AEAD nonce",
450            RngOutputKind::Argon2Salt16 => "Argon2 16-byte salt",
451            RngOutputKind::Argon2Salt32 => "Argon2 32-byte salt",
452        };
453        write!(f, "{detail}")
454    }
455}
456
457/// Specific reason secure random generation failed.
458#[derive(Debug, Clone, Copy, PartialEq, Eq)]
459pub enum RngFailureKind {
460    /// The system entropy source was unavailable.
461    EntropyUnavailable,
462    /// The requested output length was unacceptable.
463    InvalidOutputLength,
464}
465
466impl core::fmt::Display for RngFailureKind {
467    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
468        let detail = match self {
469            RngFailureKind::EntropyUnavailable => "entropy unavailable",
470            RngFailureKind::InvalidOutputLength => "invalid output length",
471        };
472        write!(f, "{detail}")
473    }
474}
475
476/// Specific reason a constant-time comparison did not match.
477#[derive(Debug, Clone, Copy, PartialEq, Eq)]
478pub enum ConstantTimeFailureKind {
479    /// The two inputs had different lengths.
480    LengthMismatch,
481    /// The two inputs had equal length but unequal contents.
482    NotEqual,
483}
484
485impl core::fmt::Display for ConstantTimeFailureKind {
486    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
487        let detail = match self {
488            ConstantTimeFailureKind::LengthMismatch => "length mismatch",
489            ConstantTimeFailureKind::NotEqual => "not equal",
490        };
491        write!(f, "{detail}")
492    }
493}
494
495/// Typed error taxonomy for all crypto operations in the workspace.
496#[derive(Debug, Error, Clone, PartialEq, Eq)]
497pub enum CryptoError {
498    /// Supplied key material was malformed or otherwise invalid.
499    #[error("invalid key material")]
500    InvalidKey,
501
502    /// An AEAD key did not have the length the cipher requires.
503    #[error("invalid AEAD key length: expected {expected} bytes, got {actual} bytes")]
504    InvalidAeadKeyLength {
505        /// Key length in bytes the cipher requires.
506        expected: usize,
507        /// Key length in bytes that was supplied.
508        actual: usize,
509    },
510
511    /// An AEAD nonce did not have the length the cipher requires.
512    #[error("invalid AEAD nonce length: expected {expected} bytes, got {actual} bytes")]
513    InvalidAeadNonceLength {
514        /// Nonce length in bytes the cipher requires.
515        expected: usize,
516        /// Nonce length in bytes that was supplied.
517        actual: usize,
518    },
519
520    /// A ciphertext was shorter than the minimum (tag) length.
521    #[error("invalid ciphertext length: minimum {minimum} bytes, got {actual} bytes")]
522    InvalidCiphertextLength {
523        /// Minimum ciphertext length in bytes (the authentication tag length).
524        minimum: usize,
525        /// Ciphertext length in bytes that was supplied.
526        actual: usize,
527    },
528
529    /// AEAD encryption failed in the given backend for the given reason.
530    #[error("AEAD encryption failed in {backend} backend: {kind}")]
531    AeadEncrypt {
532        /// Backend lane in which the failure occurred.
533        backend: AeadBackend,
534        /// Specific encryption failure cause.
535        kind: AeadFailureKind,
536    },
537
538    /// AEAD decryption failed in the given backend for the given reason.
539    #[error("AEAD decryption failed in {backend} backend: {kind}")]
540    AeadDecrypt {
541        /// Backend lane in which the failure occurred.
542        backend: AeadBackend,
543        /// Specific decryption failure cause (includes authentication failure).
544        kind: AeadFailureKind,
545    },
546
547    /// A signature operation failed in the given backend for the given reason.
548    #[error("signature failed in {backend} backend during {operation}: {kind}")]
549    Signature {
550        /// Backend lane in which the failure occurred.
551        backend: SignatureBackend,
552        /// Operation (sign, verify, keygen, encode) that failed.
553        operation: SignatureOperation,
554        /// Specific signature failure cause.
555        kind: SignatureFailureKind,
556    },
557
558    /// A key agreement operation failed for the given reason.
559    #[error("key agreement failed: {kind}")]
560    KeyAgreementFailure {
561        /// Specific key-agreement failure cause.
562        kind: KeyAgreementFailureKind,
563    },
564
565    /// A KEM (key encapsulation) operation failed for the given reason.
566    #[error("KEM operation failed: {kind}")]
567    KemFailure {
568        /// Specific KEM failure cause.
569        kind: KemFailureKind,
570    },
571
572    /// A key-wrap operation failed for the given algorithm and reason.
573    #[error("key wrap failed for {algorithm} during {operation}: {kind}")]
574    KeyWrap {
575        /// Key-wrap algorithm that failed.
576        algorithm: KeyWrapAlgorithm,
577        /// Operation (wrap or unwrap) that failed.
578        operation: KeyWrapOperation,
579        /// Specific key-wrap failure cause.
580        kind: KeyWrapFailureKind,
581    },
582
583    /// A password-based KDF operation failed for the given algorithm/profile.
584    #[error("KDF failed for {algorithm}/{profile}: {kind}")]
585    Kdf {
586        /// KDF algorithm that failed.
587        algorithm: KdfAlgorithm,
588        /// Cost profile in effect at the time of failure.
589        profile: KdfProfile,
590        /// Specific KDF failure cause.
591        kind: KdfFailureKind,
592    },
593
594    /// An HKDF operation failed for the given hash and reason.
595    #[error("HKDF failed for {hash}: {kind}")]
596    Hkdf {
597        /// Hash suite underlying the HKDF operation.
598        hash: HkdfHash,
599        /// Specific HKDF failure cause.
600        kind: HkdfFailureKind,
601    },
602
603    /// An HMAC operation failed for the given hash and reason.
604    #[error("HMAC failed for {hash}: {kind}")]
605    Mac {
606        /// Hash suite underlying the HMAC operation.
607        hash: MacHash,
608        /// Specific HMAC failure cause.
609        kind: MacFailureKind,
610    },
611
612    /// Secure random generation failed for the given output purpose.
613    #[error("secure random generation failed for {output}: {kind}")]
614    Rng {
615        /// Purpose the requested random bytes were being generated for.
616        output: RngOutputKind,
617        /// Specific RNG failure cause.
618        kind: RngFailureKind,
619    },
620
621    /// A constant-time comparison did not match, with the two input lengths.
622    #[error("constant-time comparison failed: {kind}")]
623    ConstantTimeComparison {
624        /// Specific comparison failure cause.
625        kind: ConstantTimeFailureKind,
626        /// Length in bytes of the left-hand input.
627        left_len: usize,
628        /// Length in bytes of the right-hand input.
629        right_len: usize,
630    },
631
632    /// The requested operation is not supported.
633    #[error("unsupported operation")]
634    Unsupported,
635}