jdx/mise · error
[experimental] No age recipients provided. Use…
Error message
[experimental] No age recipients provided. Use --age-recipient, --age-ssh-recipient, or --age-key-file
What it means
`mise set --encrypt` (experimental age-based encryption) collects age recipients from --age-recipient, --age-ssh-recipient, and --age-key-file. If none of these flags supplied any recipient, encryption cannot produce a valid age header, so mise refuses to proceed. This is an experimental-gated validation of required encryption inputs.
Solutions
- Pass at least one recipient, e.g. `mise set --encrypt --age-recipient age1... KEY=value`.
- Use `--age-ssh-recipient ssh-ed25519 AAAA...` to encrypt to an SSH key.
- Use `--age-key-file <path>` pointing at an age identity/keys file with valid recipients; verify the file loads.
Example fix
// before mise set --encrypt DB_PASS=secret // error: no age recipients provided // after mise set --encrypt --age-recipient age1qy... DB_PASS=secret
Defensive patterns
Strategy: validation
Validate before calling
test -n "$AGE_RECIPIENT$AGE_SSH_RECIPIENT$AGE_KEY_FILE" || { echo 'provide an age recipient flag' >&2; exit 2; } Try / catch
mise set --encrypt --age-recipient "$RECIPIENT" KEY=value || { echo 'encryption failed: check recipient/key file' >&2; } Prevention
- Store the recipient in a shell variable or config and always pass one of the three flags
- Validate the key file loads (age-compatible format) before scripting
- Remember the feature is experimental — check `mise settings get experimental`
When it happens
Trigger: Running `mise set --encrypt KEY=value` (with the experimental age setting enabled) without any of --age-recipient, --age-ssh-recipient, or --age-key-file, or with flags that yield an empty recipient list.
Common situations: Forgetting the recipient flags on first use of encrypted env; providing only a key-file path that fails to load (so recipients stays empty); scripting the encrypt command without forwarding recipient flags.
Understand the failure class
Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.
Related errors
- compressed payload exceeds the size limit
- dotfiles: cannot enroll encrypted paths while history is…
- has no value
- no age recipients to encrypt for
- plaintext exceeds the size limit
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/f2c800eed817f720.
Report an issue: GitHub.
Appendix: source
Thrown at src/cli/set.rs:452
}
// If no recipients were provided, use defaults
if recipients.is_empty()
&& (self.age_recipient.is_empty()
&& self.age_ssh_recipient.is_empty()
&& self.age_key_file.is_none())
{
recipients = agecrypt::load_recipients_from_defaults().await?;
}
// Load recipients from key file if specified
if let Some(key_file) = &self.age_key_file {
let key_file_recipients = agecrypt::load_recipients_from_key_file(key_file).await?;
recipients.extend(key_file_recipients);
}
if recipients.is_empty() {
bail!(
"[experimental] No age recipients provided. Use --age-recipient, --age-ssh-recipient, or --age-key-file"
);
}
Ok(recipients)
}
}
async fn get_mise_toml(filename: &Path) -> Result<MiseToml> {
let path = env::current_dir()?.join(filename);
// Before the exists/does-not-exist split, so a `.tool-versions` says why it is refused instead
// of failing later as invalid TOML, and so a name mise cannot read back is never created.
crate::config::config_file::ensure_writable_as_toml(&path).await?;
let mise_toml = if path.exists() {
MiseToml::from_file(&path)?
} else {
MiseToml::init(&path)
};View on GitHub (pinned to 533346cc37)