jdx/mise · error

--postinstall requires a TOML config file

Error message

--postinstall requires a TOML config file

What it means

`mise use --postinstall` writes a tool target with a postinstall hook into the active config file. mise only supports persisting postinstall directives in TOML-based config files (mise.toml / .mise.toml etc.), so it throws this bail when any --postinstall target is requested while the resolved config source is not a MiseToml file (e.g. .tool-versions, or no config file at all).

Solutions

  1. Convert the project config to mise.toml (e.g. `mise use` without --postinstall first creates/uses mise.toml, or rename/migrate .tool-versions to mise.toml) and re-run with --postinstall.
  2. Put the tool plus [tools] postinstall hook directly in mise.toml instead of using the CLI flag.
  3. Drop --postinstall and run the install hook manually via `mise install` scripts or a task.

Example fix

// before (fails: .tool-versions present)
mise use --postinstall "npm run prepare" node@22
// after
cat > mise.toml <<'EOF'
[tools]
node = "22"
EOF
mise use --postinstall "npm run prepare" node@22
Defensive patterns

Strategy: validation

Validate before calling

if mise_use_args.contains('--postinstall') && !config_path.ends_with(".toml") {
  eprintln!('--postinstall needs a mise.toml config; migrate .tool-versions first');
}

Try / catch

match mise_use(&args) {
  Err(e) if e.to_string().contains("requires a TOML config file") => migrate_to_mise_toml()? ,
  r => r?,
}

Prevention

When it happens

Trigger: Running `mise use --postinstall <cmd> tool@version` (ToolArg.postinstall set) when `get_config_file().source()` is not ToolSource::MiseToml — e.g. the project uses .tool-versions, only a global non-TOML source resolves, or no config file exists in the current directory tree.

Common situations: Projects still using asdf-style .tool-versions files; users in a directory with no mise config so `mise use` would fall back to creating a non-TOML config; scripts that pass --postinstall to a `mise use` invocation pointed at legacy configs.

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@533346cc37 (2026-09-17). Data as JSON: /api/errors/19777e65ff4bb15b. Report an issue: GitHub.

Appendix: source

Thrown at src/cli/use.rs:267

            .iter()
            .map(|target| target.tool.clone())
            .collect::<Vec<_>>();
        env::TOOL_ARGS.write().unwrap().clone_from(&tool_args);
        let mut config = Config::get().await?;
        let scope = if self.global {
            ConfigScope::GlobalOnly
        } else {
            ConfigScope::All
        };
        let mut ts = ToolsetBuilder::new()
            .with_scope(scope)
            .build(&config)
            .await?;
        let mut cf = self.get_config_file().await?;
        if self.tools.iter().any(|target| target.postinstall.is_some())
            && !matches!(cf.source(), ToolSource::MiseToml(_))
        {
            bail!("--postinstall requires a TOML config file");
        }
        if self
            .tools
            .iter()
            .any(|target| !target.tool_option.is_empty())
            && !matches!(cf.source(), ToolSource::MiseToml(_))
        {
            bail!("--tool-option requires a TOML config file");
        }
        let pin = self.pin || !self.fuzzy && (Settings::get().pin || Settings::get().asdf_compat);
        let mut resolve_options = ResolveOptions {
            latest_versions: false,
            use_locked_version: true,
            resolve_rolling_channels: false,
            prefer_exact_version: pin,
            before_date: self.get_before_date()?,
            before_date_from_default: false,
            filter_installed_versions_by_release_date: false,

View on GitHub (pinned to 533346cc37)