jdx/mise · error

packslip plugin version must not be empty

Error message

packslip plugin version must not be empty

What it means

After splitting a packslip source on `#` (defaulting the request to "latest"), parse in src/plugins/packslip.rs rejects an empty version request. An empty request can only occur with a trailing/empty fragment like `packslip:github.com/owner/repo#`, so the guard keeps malformed specs out of the toolset.

Source

Thrown at src/plugins/packslip.rs:37

#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct Source {
    project: String,
    request: String,
}

impl Source {
    pub(crate) fn parse(value: &str) -> Result<Option<Self>> {
        let Some(value) = value.strip_prefix("packslip:") else {
            return Ok(None);
        };
        let (project, request) = value.split_once('#').unwrap_or((value, "latest"));
        let project = project_name(project)?;
        ensure!(
            project.starts_with("github.com/") && packslip::model::repository(&project).is_some(),
            "packslip plugin sources currently require a GitHub repository"
        );
        ensure!(
            !request.is_empty(),
            "packslip plugin version must not be empty"
        );
        Ok(Some(Self {
            project,
            request: request.to_owned(),
        }))
    }

    pub(crate) fn url(&self) -> String {
        format!("packslip:{}#{}", self.project, self.request)
    }

    pub(crate) fn with_version(mut self, version: Option<String>) -> Self {
        if let Some(version) = version {
            self.request = version;
        }
        self

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Remove the trailing `#` to use the default `latest` request: `packslip:github.com/owner/repo`.
  2. Pin an actual version after the `#`: `packslip:github.com/owner/repo#1.2.3`.
  3. Fix the script/template so the version variable is non-empty before substitution.

Example fix

// before
[tools]
gh = "packslip:github.com/cli/cli#"

// after
[tools]
gh = "packslip:github.com/cli/cli"
Defensive patterns

Strategy: validation

Validate before calling

// ensure version fragment is non-empty before building the spec
[ -n "${VERSION:-}" ] || unset VERSION
spec="packslip:github.com/owner/repo${VERSION:+#${VERSION}}"

Type guard

fn has_version_request(src: &str) -> bool {
    match src.split_once('#') {
        Some((_, req)) => !req.is_empty(),
        None => true,
    }
}

Prevention

When it happens

Trigger: A source string ending in `#` with nothing after it — e.g. `mise use 'packslip:github.com/owner/repo#'` or `[tools] x = "packslip:github.com/owner/repo#"` in mise.toml, or a template/variable that interpolated to an empty version.

Common situations: A script substitutes `${VERSION}` that is unset, leaving `repo#${VERSION}` empty; a hand-edited mise.toml left a dangling `#`; copy-paste truncation of a pinned version.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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