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
- Add the host= prefix and '=' to the stampers entry
- 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
- Always write stampers entries as host=PIN on one line
- Copy the full 'host=...' form from docs, not just the key
- Validate mise.toml after hand-editing the stampers section
- Use a .pub path or https:// identity instead of inlining keys when unsure
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
- packslip.stampers entry {spec:?}: {host:?} is not a host nam
- Invalid checksum format: {}
- Invalid platform format '{}'. Expected 'os-arch' or 'os-arch
- must not record a pin before replacement succeeds
- remote cache blob packs require a positive max_pack_bytes li
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/263ea6f2285429d4.
Report an issue: GitHub.