Skip to main content

EncryptError

Enum EncryptError 

Source
pub enum EncryptError {
    NoRecipients,
    InvalidRecipient {
        recipient: String,
        reason: String,
    },
    Failed(String),
    Io(Error),
}
Expand description

Errors that can happen during encryption operations.

§Overview

EncryptError enumerates every failure path specific to encryption: invalid recipient keys, missing recipients, internal encryption failures, and I/O glitches. It is the symmetric counterpart to [DecryptError] and follows the same design principles:

  • Fine‑grained – callers can distinguish between “no recipients” and “invalid recipient X” and act accordingly (e.g., ask the user to provide a correct key).
  • Context‑rich – the error variants carry the problematic data (recipient field) and a reason string, so error messages are self‑contained and helpful.
  • Ergonomic – automatic From conversions mean minimal boilerplate inside the encryption functions.

All public encryption APIs return crate::errors::Result<T>, where crate::errors::Error can hold an EncryptError via the #[from] conversion.

§Example: Basic error handling with public API

use age_crypto::{encrypt_with_passphrase, Error};

let plaintext = b"Secret message";
let passphrase = "my-strong-passphrase";

match encrypt_with_passphrase(plaintext, passphrase) {
    Ok(encrypted) => {
        println!("Encrypted {} bytes", encrypted.as_bytes().len());
    }
    Err(Error::Encrypt(e)) => {
        eprintln!("Encryption error: {}", e);
    }
    Err(e) => {
        eprintln!("Unexpected error: {}", e);
    }
}

§Example: Distinguishing specific error variants

use age_crypto::{encrypt_with_passphrase, Error};
use age_crypto::errors::EncryptError;

// Contoh: mencoba encrypt dengan passphrase kosong (mungkin gagal tergantung implementasi)
let result = encrypt_with_passphrase(b"test", "");

if let Err(Error::Encrypt(err)) = result {
    match err {
        EncryptError::NoRecipients => {
            // Variant ini lebih relevan untuk key-based encryption
            eprintln!("No recipients specified");
        }
        EncryptError::InvalidRecipient { recipient, reason } => {
            eprintln!("Recipient '{}' is invalid: {}", recipient, reason);
        }
        EncryptError::Failed(msg) => {
            eprintln!("Encryption failed internally: {}", msg);
        }
        EncryptError::Io(e) => {
            eprintln!("I/O error during encryption: {}", e);
        }
    }
}

§Error handling philosophy

  • No panics – all error paths return a Result; the library never aborts due to invalid input.
  • Transparent wrapping – underlying library errors (from the age crate) are stringified with .to_string() so that the error chain remains meaningful even if the inner error type is not exposed.
  • I/O errors are propagated automatically – see [Io] variant.

Variants§

§

NoRecipients

The list of recipients is empty.

Age encryption requires at least one valid public key so that the resulting ciphertext can be decrypted by the corresponding private key. This error is returned immediately from the parse_recipients helper when an empty slice is provided, before any cryptographic work is done.

Why not just encrypt to “no one”?
That would produce a ciphertext that cannot be decrypted, which is almost certainly a mistake. By treating this as an error, we force the caller to consciously provide a recipient.

§Example scenario

use age_crypto::errors::EncryptError;

fn validate_recipients(recips: &[String]) -> Result<(), EncryptError> {
    if recips.is_empty() {
        return Err(EncryptError::NoRecipients);
    }
    Ok(())
}

// Usage:
assert!(validate_recipients(&[]).is_err());
assert!(validate_recipients(&["age1valid...".into()]).is_ok());
§

InvalidRecipient

A specific recipient string could not be parsed as a valid X25519 public key.

Age public keys normally look like age1... followed by a Bech32 string. This variant is returned when x25519::Recipient::from_str fails. The fields are:

  • recipient: the original string that failed to parse.
  • reason: the parser’s error description (e.g., “invalid bech32”, “bad checksum”, “unsupported version”).

By including the offending string, the caller can report exactly which recipient was problematic without needing to copy it into the error themselves.

§Example: Parsing validation

use std::str::FromStr;
use age::x25519::Recipient;
use age_crypto::errors::EncryptError;

let key = "age1-invalid-key-format";

// Attempt to parse; on failure, convert to our error type
Recipient::from_str(key)
    .map_err(|e| EncryptError::InvalidRecipient {
        recipient: key.to_string(),
        reason: format!("Parse error: {}", e),
    })?;

§Example: Error output format

recipients = ["age1valid", "not-a-key", "age1another"]
-> EncryptError::InvalidRecipient {
       recipient: "not-a-key",
       reason: "invalid bech32 checksum"
   }
-> Display: "Invalid recipient 'not-a-key': invalid bech32 checksum"

Fields

§recipient: String

The original string that was supposed to be an age public key.

§reason: String

The explanation from the parser about why it is invalid.

§

Failed(String)

The encryption process encountered an internal error.

This variant covers all age‑internal failures that are not related to recipient parsing or I/O. For example:

  • Failure to generate a shared secret from a recipient’s key.
  • Failure to wrap the symmetric key.
  • Unexpected errors from the random number generator.

The inner String contains whatever error message the age crate produced. While this is not as structured as the other variants, it ensures no error is silently swallowed.

§When this occurs

This error is relatively rare in practice because the age crate is well-tested. Common triggers include:

  • Memory allocation failures during cryptographic operations
  • Unexpected state in the encryption state machine
  • Platform-specific cryptographic backend issues

§Debugging tip

If you encounter this error frequently, consider:

  1. Updating the age and age-crypto crates to latest versions
  2. Checking system resources (memory, entropy pool)
  3. Reporting the issue with the full error message for investigation
§

Io(Error)

An I/O error occurred while writing the encrypted output.

Even though our API writes into a Vec<u8>, the Encryptor uses a generic Write implementation. In extremely rare circumstances (e.g., out‑of‑memory), writing to the vector may yield an io::Error.

Because this variant is annotated with #[from] io::Error, any ? on an I/O operation inside an encryption function will automatically promote the io::Error into EncryptError::Io.

§Example of automatic I/O error conversion

use std::io::Write;
use age_crypto::errors::EncryptError;

fn write_encrypted<W: Write>(
    writer: &mut W,
    plaintext: &[u8]
) -> Result<(), EncryptError> {
    // Any io::Error from write_all is automatically converted
    // to EncryptError::Io via the `?` operator
    writer.write_all(plaintext)?;
    Ok(())
}

§Common I/O error scenarios

ErrorKindLikely cause
WriteZeroWriter returned 0 bytes written (unusual for Vec)
OutOfMemorySystem ran out of memory during allocation
InterruptedOperation interrupted by signal (rare in memory ops)

Implementations§

Source§

impl EncryptError

Source

pub fn is_user_correctable(&self) -> bool

Returns true if this error indicates a user-correctable issue (e.g., invalid recipient format) rather than an internal failure.

This can help decide whether to prompt the user to retry with different input.

§Example
use age_crypto::errors::EncryptError;

let err = EncryptError::InvalidRecipient {
    recipient: "bad-key".into(),
    reason: "invalid bech32".into(),
};

if err.is_user_correctable() {
    println!("Please check your recipient key and try again.");
}
Source

pub fn invalid_recipient(&self) -> Option<&str>

Returns the problematic recipient string if this is an InvalidRecipient error, or None otherwise.

§Example
use age_crypto::errors::EncryptError;

let err = EncryptError::InvalidRecipient {
    recipient: "age1bad...".into(),
    reason: "checksum failed".into(),
};

if let Some(bad_key) = err.invalid_recipient() {
    eprintln!("The key '{}' is invalid", bad_key);
}

Trait Implementations§

Source§

impl Debug for EncryptError

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for EncryptError

Source§

fn fmt(&self, __formatter: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for EncryptError

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<EncryptError> for Error

Source§

fn from(source: EncryptError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for EncryptError

Source§

fn from(source: Error) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V