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

  1. Pipe one key at a time: `printf '%s' "$val" | mise set --stdin FOO`
  2. Loop for multiple variables in shell: `while read -r key val; do printf '%s' "$val" | mise set --stdin "$key"; done < secrets.tsv`
  3. 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

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


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/4e85d932f10a30a1. Report an issue: GitHub.