jdx/mise · error · eyre::Report

invalid system package spec

Error message

invalid system package spec '{spec}': expected '<manager>:<package>[@version]'

What it means

When parsing a 'mise bootstrap packages use' spec of the form manager:package[@version], the parser splits on ':' and then on '@'. If more than one colon is present (split_once yields Some((_, remaining)) where remaining still contains ':'), the spec is structurally invalid and mise bails.

Solutions

  1. Use '@' for the version instead of a colon: apt:curl@8.5 instead of apt:curl:8.5
  2. Include only one colon separating manager from package
  3. Rewrite the spec in your bootstrap packages use config

Example fix

// before
mise bootstrap packages use apt:curl:8.5
// after
mise bootstrap packages use apt:curl@8.5
Defensive patterns

Strategy: validation

Validate before calling

const valid = /^[^:]+:[^:@]+(@[^:]+)?$/.test(spec); // "mgr:pkg" or "mgr:pkg@ver"

Prevention

When it happens

Trigger: Passing a spec like 'apt:curl:latest' or 'apt:httpie:extra' — i.e. a second colon after the manager — to parse_use_spec; the Some(_) arm of the split match fires.

Common situations: Reusing the full 'apt:curl' style spec where only manager-relative 'curl@1.0' is accepted after the first colon; concatenating manager+package+version with colons instead of '@'.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at src/system/mod.rs:451

                name: rest.to_string(),
                version: None,
                tap_url: None,
                desired: packages::PackageDesiredState::Present,
            },
        ));
    }
    match rest.rsplit_once('@') {
        Some((name, version)) if !name.is_empty() && !version.is_empty() => Ok((
            mgr,
            PackageRequest {
                name: name.to_string(),
                version: (version != "latest").then(|| version.to_string()),
                tap_url: None,
                desired: packages::PackageDesiredState::Present,
            },
        )),
        Some(_) => {
            bail!("invalid system package spec '{spec}': expected '<manager>:<package>[@version]'")
        }
        None => Ok((
            mgr,
            PackageRequest {
                name: rest.to_string(),
                version: None,
                tap_url: None,
                desired: packages::PackageDesiredState::Present,
            },
        )),
    }
}

/// Build [`ManagerPackages`] from already-parsed requests (used by
/// `mise bootstrap packages use`, where version pins come from the CLI spec). Unknown or
/// settings-excluded managers are hard errors.
pub(crate) fn packages_from_requests(
    by_mgr: IndexMap<String, Vec<PackageRequest>>,

View on GitHub (pinned to 533346cc37)