jdx/mise · error · eyre::Report

conflicting aqua var `{key}`: use only one spelling

Error message

conflicting aqua var `{key}`: use only one spelling

What it means

The aqua backend merges three spellings of tool options that set aqua registry vars into one canonical map: a nested `vars = { name = value }` table, dotted `vars.name` keys, and legacy bare top-level keys. If the same var name reaches the merge twice - for example both `vars.foo` and `vars = { foo = ... }` in one tool's options - the configuration is ambiguous and option parsing stops with this error instead of silently picking a winner.

Source

Thrown at src/backend/aqua.rs:130

            }

            let key = if let Some(key) = key.strip_prefix("vars.") {
                key.to_string()
            } else {
                key.clone()
            };
            Self::insert_var_option(&mut vars, key, value)?;
        }
        Ok(vars)
    }

    fn insert_var_option<'b>(
        result: &mut BTreeMap<String, &'b toml::Value>,
        key: String,
        value: &'b toml::Value,
    ) -> Result<()> {
        if result.contains_key(&key) {
            bail!("conflicting aqua var `{key}`: use only one spelling");
        }
        result.insert(key, value);
        Ok(())
    }

    fn insert_nested_var_options<'b>(
        result: &mut BTreeMap<String, &'b toml::Value>,
        table: &'b toml::Table,
    ) -> Result<()> {
        for (key, value) in table {
            Self::insert_var_option(result, key.clone(), value)?;
        }
        Ok(())
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct AquaFileLink {

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Keep one spelling per var - prefer the documented nested table: `vars = { go_version = "1.24" }`.
  2. Remove the duplicated dotted (`vars.go_version`) or bare legacy key from the same tool's options.
  3. Re-run `mise ls` or the failing command after the fix to confirm the TOML parses.

Example fix

# before - two spellings of the same var
[tools]
"aqua:scenarigo/scenarigo" = { version = "0.21.0", vars.go_version = "1.23", vars = { go_version = "1.24" } }

# after - single spelling
[tools]
"aqua:scenarigo/scenarigo" = { version = "0.21.0", vars = { go_version = "1.24" } }
Defensive patterns

Strategy: validation

Validate before calling

// lint tool options before install: no var may arrive via two spellings
let dotted: HashSet<&str> = opts.keys().filter_map(|k| k.strip_prefix("vars.")).collect();
let table: HashSet<&str> = opts
    .get("vars")
    .and_then(|v| v.as_table())
    .map(|t| t.keys().map(String::as_str).collect())
    .unwrap_or_default();
if !dotted.is_disjoint(&table) {
    return Err(eyre::eyre!("remove the duplicate vars spelling in mise.toml"));
}

Prevention

When it happens

Trigger: In mise.toml, configuring one tool entry with two spellings of the same var: `[tools] "aqua:x/y" = { version = "1", vars.os = "linux", vars = { os = "darwin" } }`, or combining a bare legacy key (`os = ...`) with a `vars` table containing the same name. Any aqua install/version resolution then fails during `canonical_var_options`.

Common situations: Copy-pasting config examples that use different spellings into a single tool entry; migrating from dotted keys to the `vars` table and leaving the old key behind.

Related errors


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