jdx/mise · error
--stdin requires exactly one environment variable key
Error message
--stdin requires exactly one environment variable key
What it means
`mise set --stdin` reads one variable's value from stdin (like `gh secret set`) and therefore accepts exactly one environment variable key. The code checks env_vars.len() != 1 after prompt handling and bails, so passing two or more keys (or relying on stdin while naming multiple variables) is rejected before anything is read.
Source
Thrown at src/cli/set.rs:179
// Prompt for values if requested
if self.prompt {
let theme = crate::ui::theme::get_theme();
for ev in &mut env_vars {
if ev.value.is_none() {
let prompt_msg = format!("Enter value for {}", ev.key);
let value = Input::new(&prompt_msg)
.password(self.age_encrypt) // Mask input if encrypting
.theme(&theme)
.run()?;
ev.value = Some(value);
}
}
}
// Read value from stdin if requested
if self.stdin {
if env_vars.len() != 1 {
bail!("--stdin requires exactly one environment variable key");
}
let ev = &mut env_vars[0];
if ev.value.is_some() {
bail!(
"--stdin reads the value from stdin; do not provide a value with KEY=VALUE syntax"
);
}
let mut value = String::new();
std::io::stdin().read_to_string(&mut value)?;
// Strip a single trailing newline (matches `gh secret set` behavior)
if value.ends_with("\r\n") {
value.truncate(value.len() - 2);
} else if value.ends_with('\n') {
value.truncate(value.len() - 1);
}
ev.value = Some(value);
}
View on GitHub (pinned to 6f52dcdf99)
Solutions
- Pipe one key at a time: `printf '%s' "$val" | mise set --stdin FOO`
- Loop for multiple variables in shell: `while read -r key val; do printf '%s' "$val" | mise set --stdin "$key"; done < secrets.tsv`
- For non-secret bulk sets, skip stdin: `mise set FOO=1 BAR=2`
Example fix
# before echo secret | mise set --stdin API_TOKEN DB_PASSWORD # --stdin requires exactly one environment variable key # after printf '%s' "$token" | mise set --stdin API_TOKEN printf '%s' "$pass" | mise set --stdin DB_PASSWORD
Defensive patterns
Strategy: validation
Validate before calling
# enforce the one-key contract before piping
set -euo pipefail
[ "$#" -eq 1 ] || { echo 'usage: set_secret KEY (value on stdin)' >&2; exit 2; }
printf '%s' "$secret" | mise set --stdin "$1" Type guard
is_single_bare_key() { [ "$#" -eq 1 ] && case "$1" in *=*) return 1;; *) return 0;; esac; } Try / catch
Catch and surface the message directly to the operator — it is a usage contract violation; fix the call site (one key per --stdin invocation) instead of retrying.
Prevention
- Model mise set --stdin after `gh secret set`: exactly one key per pipe
- Loop per variable when setting multiple secrets from a file
- Reserve --stdin for secrets; use KEY=VALUE form for bulk plain sets
When it happens
Trigger: Running `mise set --stdin FOO BAR`, or `echo val | mise set --stdin A B`, i.e. any --stdin invocation whose positional arguments are not exactly one bare key.
Common situations: Scripts trying to set several secrets in one pass through a single pipe; misunderstanding the gh-secret-style one-key-per-invocation contract.
Understand the failure class
Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.
Related errors
- --stdin reads the value from stdin; do not provide a value w
- Environment variable {key} not found
- {} has no value
- Environment variable {} not found
- cannot link {} to its own install path
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/4e85d932f10a30a1.
Report an issue: GitHub.