jdx/mise · error

invalid system package spec '{spec}': expected '<manager>:<p

Error message

invalid system package spec '{spec}': expected '<manager>:<package>' (e.g. "apt:curl")

What it means

parse_spec parses a system package spec for `mise bootstrap packages` and requires the strict form `<manager>:<package>`. It bails when the spec has no colon at all, or the colon exists but the manager or package side is empty. Versioned names like brew:postgresql@17 keep the whole remainder as the package name.

Source

Thrown at src/system/mod.rs:361

    BrewCask { adopt: BTreeSet<String> },
}

impl ManagerPackageOptions {
    #[cfg(unix)]
    pub(crate) fn brew_cask_adopt(&self, name: &str) -> bool {
        matches!(self, Self::BrewCask { adopt } if adopt.contains(name))
    }
}

/// Split a `"manager:package"` spec (config key or CLI argument). Only the
/// first `:` separates — apt arch qualifiers ("apt:gcc:arm64") and brew
/// versioned formula names ("brew:postgresql@17") stay part of the package.
pub(crate) fn parse_spec(spec: &str) -> eyre::Result<(String, String)> {
    match spec.split_once(':') {
        Some((mgr, pkg)) if !mgr.is_empty() && !pkg.is_empty() => {
            Ok((mgr.to_string(), pkg.to_string()))
        }
        _ => bail!(
            "invalid system package spec '{spec}': expected '<manager>:<package>' (e.g. \"apt:curl\")"
        ),
    }
}

/// Split a `mise bootstrap packages use` spec `manager:package[@version]` into its parts.
///
/// `@version` mirrors `mise use tool@version`; `@latest` (or no `@`) means no
/// pin. brew and brew-cask are exempt from `@` parsing: `@` is part of
/// Homebrew names (`postgresql@17` — that name IS brew's versioning
/// mechanism), and bottles/casks can't be installed at a pinned version
/// anyway. mas uses numeric ADAM IDs only.
pub(crate) fn parse_use_spec(spec: &str) -> eyre::Result<(String, PackageRequest)> {
    let (mgr, rest) = parse_spec(spec)?;
    let rest = normalize_use_spec_package_name(&mgr, &rest)?;
    validate_package_name(&mgr, rest)?;
    if is_opaque_package_manager(&mgr) {
        return Ok((

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Prefix the spec with the package manager: "apt:curl", "brew:ripgrep", "mas:Xcode"
  2. Fix empty manager or package parts in your config or CLI arg (":curl" -> "apt:curl", "apt:" -> "apt:curl")
  3. For config files, ensure every entry is in manager:package form

Example fix

// before (mise.toml or CLI)
//   mise bootstrap packages use curl
// after
//   mise bootstrap packages use apt:curl
Defensive patterns

Strategy: validation

Validate before calling

// Validate a system package spec before passing it to mise:
function isValidPackageSpec(spec: string): boolean {
  const i = spec.indexOf(":");
  if (i <= 0 || i === spec.length - 1) return false;
  return !spec.slice(0, i).includes(":") && spec.slice(i + 1).length > 0;
}
// isValidPackageSpec("apt:curl") === true; isValidPackageSpec("curl") === false

Type guard

function isManagerPrefixed(s: string): s is `${string}:${string}` {
  const i = s.indexOf(":");
  return i > 0 && i < s.length - 1;
}

Try / catch

try {
  await mise(["bootstrap", "packages", "use", spec]);
} catch (e) {
  if (String(e).includes("expected '<manager>:<package>'")) {
    throw new Error(`Spec "${spec}" needs a manager prefix, e.g. apt:${spec}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a string without a `manager:` prefix (e.g. "curl" instead of "apt:curl"), an empty manager (":curl"), or an empty package ("apt:"), via parse_use_spec, package_requests_from_config_files, or packages_from_specs_with_config.

Common situations: Forgetting the manager prefix in mise.toml [packages] entries or on the `mise bootstrap packages use` command line; copying a plain OS package name from apt/brew docs; a config file line like curl = true instead of apt:curl.

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@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/107003a966f9ff14. Report an issue: GitHub.