jdx/mise · error · eyre::Report

No tool specified and not running interactively

Error message

No tool specified and not running interactively

What it means

`mise use` with no tool arguments opens an interactive tool selector (demand::Select). That requires a TTY on stderr; when stderr is not user-attended (CI, piped output, non-interactive shell) tool_selector bails at src/cli/use.rs:364 rather than hanging on an invisible prompt.

Source

Thrown at src/cli/use.rs:364

                    style("mise").green(),
                    style(&path).cyan().for_stderr(),
                );
            }
            if !remove.is_empty() {
                let tools_to_remove = remove.iter().map(|r| r.to_string()).join(", ");
                miseprintln!(
                    "{} {} removed: {tools_to_remove}",
                    style("mise").green(),
                    style(&path).cyan().for_stderr(),
                );
            }
        }
        Ok(())
    }

    fn tool_selector(&self) -> Result<ToolArg> {
        if !console::user_attended_stderr() {
            bail!("No tool specified and not running interactively");
        }
        let theme = crate::ui::theme::get_theme();
        let mut s = demand::Select::new("Tools")
            .description("Select a tool to install")
            .filtering(true)
            .filterable(true)
            .theme(&theme);
        for rt in REGISTRY.values().unique_by(|r| r.short) {
            if let Some(backend) = rt.backends().first() {
                // TODO: populate registry with descriptions from aqua and other sources
                // TODO: use the backend from the lockfile if available
                let description = rt.description.unwrap_or(backend);
                s = s.option(demand::DemandOption::new(rt).description(description));
            }
        }
        ctrlc::show_cursor_after_ctrl_c();
        match s.run() {
            Ok(rt) => rt.short.parse(),

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Pass the tool explicitly: `mise use node@22` — no prompt needed
  2. Run the command in a real interactive terminal if you wanted the selector
  3. For scripts, resolve versions ahead of time and feed them as args (optionally from mise.lock/registry)

Example fix

# before
$ mise use | tee log.txt   # or in CI
# error: No tool specified and not running interactively

# after
$ mise use node@22
Defensive patterns

Strategy: validation

Validate before calling

# never rely on the interactive selector in scripts
if [ -t 2 ] && [ $# -eq 0 ]; then mise use; else mise use "${1:?usage: mise use <tool>[@version]}"; fi

Try / catch

mise use "$tool" || { echo 'non-interactive: pass an explicit tool@version to mise use' >&2; exit 1; }

Prevention

When it happens

Trigger: Bare `mise use` in CI, cron, Docker build, or any context where stderr is redirected/piped (console::user_attended_stderr() == false).

Common situations: Bootstrap scripts assuming interactivity; running mise inside `docker build`; SSH one-shot commands without TTY; piping mise output to tee.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/3c92940e206126eb. Report an issue: GitHub.