jdx/mise · error

compressed payload exceeds the size limit

Error message

compressed payload exceeds the size limit

What it means

After zstd compression, encrypt_bytes checks the compressed length against MAX_ENCRYPTED_BYTES. Even if the original plaintext fit, incompressible data can still exceed the ciphertext budget, so the function bails before encryption rather than producing an oversized payload.

Solutions

  1. Reduce the input size — split into multiple encryptions below the limit
  2. Check whether the payload is already compressed; store it out-of-band and encrypt a reference/key instead
  3. Trim unnecessary fields from the payload (debug data, duplicated secrets) before encrypting
  4. Increase the limit only if your deployment explicitly supports larger encrypted payloads

Example fix

// before
let compressed = zstd::encode_all(&binary_blob, LEVEL)?; // still too large
let ct = encrypt_bytes(&binary_blob, &recipients)?;
// after
let key = generate_key();
store_out_of_band(&binary_blob, &key)?;
let ct = encrypt_bytes(&key, &recipients)?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: pre-check post-compression size
let compressed = zstd::encode_all(plaintext, 3)?;
anyhow::ensure!(compressed.len() as u64 <= MAX_ENCRYPTED_BYTES, "compressed payload too large");

Type guard

fn compressed_fits(plaintext: &[u8], max: u64) -> std::io::Result<bool> {
    Ok(zstd::encode_all(plaintext, 3)?.len() as u64 <= max)
}

Try / catch

match encrypt_bytes(&data, &recipients) {
    Err(e) if e.to_string().contains("compressed payload exceeds") => {
        eprintln!("data is incompressible and too large; chunk or store out-of-band");
    }
    other => other,
}

Prevention

When it happens

Trigger: zstd::encode_all returns a buffer whose len() > MAX_ENCRYPTED_BYTES — encrypting already-compressed/high-entropy data near the plaintext limit.

Common situations: Encrypting binary blobs (images, archives) that zstd cannot shrink, plaintext just under MAX_PLAINTEXT_BYTES where the compressed form still overflows, accidentally encrypting an already-compressed file.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/dafb4181a2339367. Report an issue: GitHub.

Appendix: source

Thrown at src/agecrypt.rs:161

        ));
    }
    Ok(bytes)
}

/// zstd-compressed, then age-encrypted for `recipients`.
pub(crate) fn encrypt_bytes(
    plaintext: &[u8],
    recipients: &[Box<dyn Recipient + Send>],
) -> Result<Vec<u8>> {
    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> {

View on GitHub (pinned to 533346cc37)