jdx/mise · error
encrypted payload exceeds the size limit
Error message
encrypted payload exceeds the size limit
What it means
After age-encrypting the compressed data, encrypt_bytes verifies the final ciphertext vector does not exceed MAX_ENCRYPTED_BYTES; age framing adds overhead, so even an acceptable compressed input can yield slightly larger output. If out.len() exceeds the limit the result is discarded and the error is raised.
Source
Thrown at src/agecrypt.rs:171
if recipients.is_empty() {
bail!("no age recipients to encrypt for");
}
if plaintext.len() as u64 > MAX_PLAINTEXT_BYTES {
bail!("plaintext exceeds the size limit");
}
let compressed = zstd::encode_all(plaintext, ZSTD_COMPRESSION_LEVEL)?;
if compressed.len() as u64 > MAX_ENCRYPTED_BYTES {
bail!("compressed payload exceeds the size limit");
}
let encryptor =
Encryptor::with_recipients(recipients.iter().map(|r| r.as_ref() as &dyn Recipient))
.map_err(|e| eyre!("creating the age encryptor: {e}"))?;
let mut out = Vec::new();
let mut writer = encryptor.wrap_output(&mut out)?;
writer.write_all(&compressed)?;
writer.finish()?;
if out.len() as u64 > MAX_ENCRYPTED_BYTES {
bail!("encrypted payload exceeds the size limit");
}
Ok(out)
}
pub(crate) async fn decrypt_bytes_mode(
ciphertext: &[u8],
interactive: bool,
) -> Result<Vec<u8>, DecryptError> {
if ciphertext.len() as u64 > MAX_ENCRYPTED_BYTES {
return Err(DecryptError::Corrupt(
"encrypted payload exceeds the size limit".into(),
));
}
let loaded = load_identities(interactive).await;
if loaded.identities.is_empty() {
if loaded.plugins > 0 {
return Err(DecryptError::Failed { error: "hardware identity requires an interactive restore with its age plugin installed".into(), hint: String::new() });
}View on GitHub (pinned to afd2eddd3a)
Solutions
- Reduce input size by a margin that accounts for age overhead (headers, chunk framing).
- Check out.len() logic: keep input well below MAX_ENCRYPTED_BYTES rather than exactly at it.
- Raise MAX_ENCRYPTED_BYTES in src/agecrypt.rs if the limit no longer fits deployment constraints.
Example fix
// before let ct = encrypt_bytes(&data, &recipients)?; // fails at the final size check due to age overhead // after let budget = MAX_ENCRYPTED_BYTES - 64 * 1024; // leave headroom for age framing assert!((data.len() as u64) <= budget, "trim data below the encrypted-size budget"); let ct = encrypt_bytes(&data, &recipients)?;
Defensive patterns
Strategy: validation
Validate before calling
let headroom: u64 = 64 * 1024; // age framing overhead
if data.len() as u64 > MAX_ENCRYPTED_BYTES - headroom {
// trim or split before encrypting
}
encrypt_bytes(&data, &recipients)?; Type guard
null
Try / catch
match encrypt_bytes(&data, &recipients) {
Ok(ct) => use(ct),
Err(e) if e.to_string().contains("encrypted payload exceeds") => retry_with_smaller_input(),
Err(e) => return Err(e),
} Prevention
- Leave headroom for age header/chunk overhead when sizing inputs.
- Keep inputs comfortably below MAX_ENCRYPTED_BYTES.
- If limits are too tight for your workload, raise them in src/agecrypt.rs deliberately.
When it happens
Trigger: encrypt_bytes produced ciphertext (compressed payload + age envelope overhead) larger than MAX_ENCRYPTED_BYTES.
Common situations: Input near the compressed-size boundary where age header/chunk overhead pushes the total over the limit; incompressible data just under the raw limit.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- plaintext exceeds the size limit
- compressed payload exceeds the size limit
- object exceeds the encrypted content size limit
- encrypted file exceeds the size limit: {path}
- no age recipients to encrypt for
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/74d150f78cd0e38e.
Report an issue: GitHub.