jdx/mise · error

plaintext exceeds the size limit

Error message

plaintext exceeds the size limit

What it means

encrypt_bytes in src/agecrypt.rs refuses to encrypt plaintext larger than MAX_PLAINTEXT_BYTES (1 GiB, line 135). The age encryption path plus zstd compression runs in memory, so an unbounded input would balloon RAM usage; the check bails early before any compression or encryption work is done.

Source

Thrown at src/agecrypt.rs:157

    reader.take(limit + 1).read_to_end(&mut bytes)?;
    if bytes.len() as u64 > limit {
        return Err(std::io::Error::other(
            "encrypted content exceeds the size limit",
        ));
    }
    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)
}

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Reduce the plaintext to under 1 GiB before encrypting (split into chunks and encrypt each).
  2. Stream or store the large artifact separately and encrypt only keys/manifests.
  3. If the 1 GiB limit is genuinely too small for your use case, raise MAX_PLAINTEXT_BYTES in src/agecrypt.rs and keep the memory tradeoff in mind.

Example fix

// before
let data = std::fs::read("huge.bin")?;
let ct = encrypt_bytes(&data, &recipients)?; // bails: plaintext exceeds the size limit
// after
let data = std::fs::read("huge.bin")?;
assert!(data.len() <= 1024 * 1024 * 1024, "split huge.bin before encrypting");
let ct = encrypt_bytes(&data, &recipients)?;
Defensive patterns

Strategy: validation

Validate before calling

const MAX_PLAINTEXT_BYTES: usize = 1024 * 1024 * 1024;
if data.len() > MAX_PLAINTEXT_BYTES {
    // split or offload before calling encrypt_bytes
}
encrypt_bytes(&data, &recipients)?;

Type guard

fn within_plaintext_limit(data: &[u8]) -> bool { data.len() as u64 <= 1024 * 1024 * 1024 }

Try / catch

match encrypt_bytes(&data, &recipients) {
    Ok(ct) => use(ct),
    Err(e) if e.to_string().contains("size limit") => split_and_encrypt_in_chunks(&data, &recipients)?,
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling encrypt_bytes (directly or via the plugin protocol / software recovery paths) with a plaintext buffer whose len() exceeds 1024*1024*1024 bytes.

Common situations: Encrypting a very large file or dump that was read fully into memory; a plugin sending an oversized payload; accidentally encrypting a directory tarball or log archive instead of a small secret.

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


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