jdx/mise · error · eyre::Report

semver requires exactly 1 argument

Error message

semver requires exactly 1 argument

What it means

command_wrapper options accept exactly four keys: content, executable, args, and env. Any other key is collected, sorted, and reported in this error (comma-joined), so the message may list several unknown keys at once.

Source

Thrown at crates/aqua-registry/src/template.rs:334

    Ok(expr)
}

fn skip_whitespace(tokens: &mut std::iter::Peekable<std::slice::Iter<Token>>) {
    while matches!(tokens.peek(), Some(Token::Whitespace(_))) {
        tokens.next();
    }
}

/// Function signature for template functions that return Value trait objects
type TemplateFn = fn(&[Box<dyn Value>]) -> Result<Box<dyn Value>>;

/// Static registry of available template functions
static FUNCTION_REGISTRY: LazyLock<HashMap<&'static str, TemplateFn>> = LazyLock::new(|| {
    let mut registry: HashMap<&'static str, TemplateFn> = HashMap::new();

    registry.insert("semver", |args| {
        if args.len() != 1 {
            bail!("semver requires exactly 1 argument");
        }
        let input = args[0].as_string();
        let clean_version = input.strip_prefix('v').unwrap_or(&input);
        let version = Versioning::new(clean_version)
            .wrap_err_with(|| format!("invalid semver version: {input}"))?;

        Ok(Box::new(SemVerValue {
            major: version.nth(0).unwrap_or(0),
            minor: version.nth(1).unwrap_or(0),
            patch: version.nth(2).unwrap_or(0),
            original: clean_version.to_string(),
        }) as Box<dyn Value>)
    });

    registry.insert("title", |args| {
        if args.len() != 1 {
            bail!("title requires exactly 1 argument");
        }

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Remove or rename the listed keys to one of content, executable, args, env
  2. Check the mise docs for the command_wrapper schema matching your mise version

Example fix

# before
{"command_wrapper": ["tool", {"executable": "bin/tool", "arg": ["--serve"]}]}
# after
{"command_wrapper": ["tool", {"executable": "bin/tool", "args": ["--serve"]}]}
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED: &[&str] = &["content", "executable", "args", "env"];
let bad: Vec<_> = opts.keys().filter(|k| !ALLOWED.contains(&k.as_str())).collect();
if !bad.is_empty() { /* reject or strip unknown keys before install */ }

Type guard

fn wrapper_options_are_supported(opts: &serde_json::Map<String, Value>) -> bool {
    opts.keys().all(|k| matches!(k.as_str(), "content" | "executable" | "args" | "env"))
}

Prevention

When it happens

Trigger: Options objects containing typo'd keys ('arg', 'envs', 'shell') or newer/misremembered option names; metadata written for a different tool's wrapper schema.

Common situations: Hand-authored mise command_wrapper metadata; schema drift between mise versions adding/renaming options.

Related errors


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