{"record":{"id":"48abebd22c10cf8c","repo":"jdx/mise","slug":"no-age-recipients-to-encrypt-for","errorCode":null,"errorMessage":"no age recipients to encrypt for","messagePattern":"no age recipients to encrypt for","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/agecrypt.rs","lineNumber":154,"sourceCode":"\npub(crate) fn read_bounded(reader: impl Read, limit: u64) -> std::io::Result<Vec<u8>> {\n    let mut bytes = Vec::new();\n    reader.take(limit + 1).read_to_end(&mut bytes)?;\n    if bytes.len() as u64 > limit {\n        return Err(std::io::Error::other(\n            \"encrypted content exceeds the size limit\",\n        ));\n    }\n    Ok(bytes)\n}\n\n/// zstd-compressed, then age-encrypted for `recipients`.\npub(crate) fn encrypt_bytes(\n    plaintext: &[u8],\n    recipients: &[Box<dyn Recipient + Send>],\n) -> Result<Vec<u8>> {\n    if recipients.is_empty() {\n        bail!(\"no age recipients to encrypt for\");\n    }\n    if plaintext.len() as u64 > MAX_PLAINTEXT_BYTES {\n        bail!(\"plaintext exceeds the size limit\");\n    }\n    let compressed = zstd::encode_all(plaintext, ZSTD_COMPRESSION_LEVEL)?;\n    if compressed.len() as u64 > MAX_ENCRYPTED_BYTES {\n        bail!(\"compressed payload exceeds the size limit\");\n    }\n    let encryptor =\n        Encryptor::with_recipients(recipients.iter().map(|r| r.as_ref() as &dyn Recipient))\n            .map_err(|e| eyre!(\"creating the age encryptor: {e}\"))?;\n    let mut out = Vec::new();\n    let mut writer = encryptor.wrap_output(&mut out)?;\n    writer.write_all(&compressed)?;\n    writer.finish()?;\n    if out.len() as u64 > MAX_ENCRYPTED_BYTES {\n        bail!(\"encrypted payload exceeds the size limit\");\n    }","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/agecrypt.rs#L136-L172","documentation":"encrypt_bytes compresses plaintext and encrypts it for a supplied list of age recipients. An empty recipient list would produce an envelope nobody can decrypt, so the function rejects it up front with this error.","triggerScenarios":"Calling encrypt_bytes (directly or via plugin protocol encryption / software recovery paths) with an empty recipients slice — e.g. no identities loaded from config, key files missing, or filtering removed all recipients.","commonSituations":"Missing or unreadable age key files (MISE_AGE_RECIPIENTS / key config); plugin recovery paths where the recipient was never registered; tests constructing encryption without adding a recipient.","solutions":["Populate the recipients list with at least one age recipient before calling encrypt_bytes.","Check that age identity/recipient configuration is present and parses (e.g. ssh-ed25519 or age1... recipients).","Verify the plugin registration/recovery path actually supplies its software-recovery recipient.","In tests, add a generated recipient (as the passing tests do) before encrypting."],"exampleFix":"// before\nlet recipients: Vec<Box<dyn Recipient + Send>> = vec![];\nencrypt_bytes(&plaintext, &recipients)?;\n// after\nlet recipients: Vec<Box<dyn Recipient + Send>> = vec![Box::new(recipient)];\nassert!(!recipients.is_empty());\nencrypt_bytes(&plaintext, &recipients)?;","handlingStrategy":"validation","validationCode":"if recipients.is_empty() {\n    return Err(anyhow!(\"no age recipients configured; check MISE age recipient settings\"));\n}","typeGuard":"fn has_recipients(recipients: &[Box<dyn Recipient + Send>]) -> bool { !recipients.is_empty() }","tryCatchPattern":"match encrypt_bytes(&plaintext, &recipients) { Err(e) if e.to_string().contains(\"no age recipients\") => { load_recipients_from_config()?; }, Err(e) => return Err(e), Ok(ciphertext) => ciphertext }","preventionTips":["Validate recipient configuration at startup","Ensure age key files exist and are readable before encrypting","Add a software-recovery recipient in plugin registration paths"],"tags":["age","encryption","config"],"backgroundTag":"empty-required-field","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}