jdx/mise · error

config set requires a TOML config file, but

Error message

config set requires a TOML config file, but {} is not TOML

What it means

`mise config set` writes TOML values, so the resolved target file must have a `.toml` extension. If the selected file resolves but is not TOML (e.g. `.tool-versions`, `.mise.toml` is fine but other formats or non-toml paths aren't), mise bails rather than corrupting a non-TOML file with toml_edit writes.

Solutions

  1. Target a TOML file: use the default mise.toml or pass `--file /path/to/mise.toml`
  2. Convert legacy `.tool-versions` to mise.toml (`mise config migrate` style tooling or copy entries into `[tools]`)
  3. For non-TOML formats use the format-appropriate command (e.g. `mise use --file .tool-versions` semantics) or edit manually

Example fix

// before
$ mise config set --file .tool-versions tools.node 20  # not TOML
// after
$ mise config set --global tools.node 20  # writes ~/.config/mise/config.toml
Defensive patterns

Strategy: validation

Validate before calling

case "$file" in *.toml) ;; *) echo "$file is not TOML"; exit 1;; esac

Type guard

is_toml_path() { case "$1" in *.toml) return 0;; *) return 1;; esac; }

Try / catch

mise config set --file "$f" "$k" "$v" 2>&1 | grep -q 'not TOML' && { echo "convert $f to mise.toml first"; exit 1; }

Prevention

When it happens

Trigger: `mise config set ... --file <path>` (or another selection) where the path does not end in `.toml` — e.g. pointing at `.tool-versions`, an idiomatic-files config, or a YAML/JSON config path.

Common situations: Users try to edit `.tool-versions` via `mise config set --file`; scripts pass a config path variable that points at a legacy format file.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/c38f3f30e83a034c. Report an issue: GitHub.

Appendix: source

Thrown at src/cli/config/set.rs:124

        let file = match self.file {
            Some(path) => Some(resolve_target_config_path(ConfigPathOptions {
                path: Some(path),
                prefer_toml: true,
                ..Default::default()
            })?),
            None if self.global => Some(resolve_target_config_path(ConfigPathOptions {
                global: true,
                prefer_toml: true,
                ..Default::default()
            })?),
            None if self.system => Some(system_config_path()),
            None => top_toml_config(),
        };
        let Some(file) = file else {
            bail!("No mise.toml file found");
        };
        if !file.to_string_lossy().ends_with(".toml") {
            bail!(
                "config set requires a TOML config file, but {} is not TOML",
                display_path(&file)
            );
        }
        if !file.exists() && !self.global && !self.system {
            bail!("config file not found: {}", display_path(&file));
        }
        let raw = match std::fs::read_to_string(&file) {
            Ok(raw) => raw,
            Err(error)
                if (self.global || self.system) && error.kind() == std::io::ErrorKind::NotFound =>
            {
                String::new()
            }
            Err(error) => return Err(error.into()),
        };
        let mut config: toml_edit::DocumentMut = raw.parse()?;
        let mut container = config.as_item_mut();

View on GitHub (pinned to 533346cc37)