jdx/mise · error

packslip.stampers entry {spec:?} has no pin; write host=PUBK

Error message

packslip.stampers entry {spec:?} has no pin; write host=PUBKEY, host=path/to/key.pub, or host=https://github.com/org/repo/

What it means

Each entry in the packslip.stampers config must have the form host=PIN, where PIN is a minisign public key, a path to a .pub file, or an https:// identity prefix. This error fires when an entry has no '=' separating host from pin.

Source

Thrown at src/packslip_stamps.rs:49

use crate::toolset::ToolVersionOptions;

/// GitHub's OIDC issuer, for a stamper pinned by a workflow identity.
const GITHUB_ISSUER: &str = "https://token.actions.githubusercontent.com";

/// A host whose stamps mise trusts, and how its lists are pinned.
pub(crate) struct Stamper {
    pub(crate) host: String,
    pin: Pin,
}

impl Stamper {
    /// `host=PIN`, where PIN is a minisign public key line, the path of a
    /// `.pub` file, or an `https://` identity prefix for a keyless signer
    /// on GitHub such as `https://github.com/org/registry/`.
    pub(crate) fn parse(spec: &str) -> Result<Stamper> {
        let spec = spec.trim();
        let Some((host, pin)) = spec.split_once('=') else {
            bail!(
                "packslip.stampers entry {spec:?} has no pin; write host=PUBKEY, host=path/to/key.pub, or host=https://github.com/org/repo/"
            );
        };
        let host = host.trim();
        let pin = pin.trim();
        if host.is_empty() || !host.contains('.') || host.contains('/') {
            bail!("packslip.stampers entry {spec:?}: {host:?} is not a host name");
        }
        let pin = if pin.starts_with("https://") {
            Pin::Identity(Policy {
                issuer: Some(GITHUB_ISSUER.into()),
                identity: None,
                identity_prefix: Some(pin.to_string()),
            })
        } else {
            let text = if std::path::Path::new(pin).is_file() {
                file::read_to_string(pin)?
            } else {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Add the host= prefix and '=' to the stampers entry
  2. Use the documented forms: host=PUBKEY, host=path/to/key.pub, or host=https://github.com/org/repo/

Example fix

// before
[packslip.stampers]
"registry.example.com"
// after
[packslip.stampers]
"registry.example.com=RWTvK7...base64key"
Defensive patterns

Strategy: validation

Validate before calling

if !spec.contains('=') {
    return Err(format!("stampers entry {spec:?} needs host=PIN form"));
}

Try / catch

match result {
    Err(e) if e.to_string().contains("has no pin") => eprintln!("fix [packslip.stampers] entry to host=PIN"),
    other => other?,
}

Prevention

When it happens

Trigger: Parsing a packslip.stampers config entry that contains no '=' character, e.g. a bare host name or a key pasted without the host= prefix.

Common situations: Typos in mise.toml/config stampers section; copying just a public key line without the host= prefix; writing host and pin on separate lines.

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/263ea6f2285429d4. Report an issue: GitHub.