jdx/mise · error

packslip: list_identity_prefix requires an issuer

Error message

packslip: list_identity_prefix requires an issuer

What it means

Applying a `list_identity_prefix` override requires the existing identity policy to carry an issuer (e.g. the Sigstore OIDC provider URL), because the prefix alone cannot pin who signed the list. If the policy has no issuer or an empty one, the override is rejected.

Solutions

  1. Add the `issuer` option, e.g. issuer = "https://token.actions.githubusercontent.com".
  2. Remove list_identity_prefix if you want the policy's default identity constraint.
  3. Switch to a `pubkey` pin if you don't want keyless identity trust at all (but then drop list_identity_prefix).

Example fix

// before
"packslip:foo" = { version = "1.0", identity = "release@vendor.example", list_identity_prefix = "https://github.com/vendor/" }

// after
"packslip:foo" = { version = "1.0", identity = "release@vendor.example", issuer = "https://token.actions.githubusercontent.com", list_identity_prefix = "https://github.com/vendor/" }
Defensive patterns

Strategy: validation

Validate before calling

function validateIssuer(opts) {
  if (opts.list_identity_prefix !== undefined && !opts.issuer) {
    throw new Error('list_identity_prefix requires an issuer');
  }
}

Prevention

When it happens

Trigger: Setting list_identity_prefix on a pin whose Identity policy was configured with `identity` only and no `issuer`, then calling release_list/github_list.

Common situations: Configuring identity = "user@example.com" without issuer for a keyless setup; vendor docs showing the prefix option but omitting that issuer is required.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src/backend/packslip.rs:572

        ),
    }
}

impl Pin {
    /// A vendor may publish its index from a different workflow than its bundles.
    /// The override replaces only the list's subject constraint, retaining the issuer.
    fn for_release_list(&self, opts: &PackslipOptions<'_>) -> Result<Self> {
        let Some(value) = opts.raw.opts.get("list_identity_prefix") else {
            return Ok(self.clone());
        };
        let Some(prefix) = value.as_str().filter(|prefix| !prefix.trim().is_empty()) else {
            bail!("packslip: list_identity_prefix must be a non-empty string");
        };
        let Self::Identity(policy) = self else {
            bail!("packslip: list_identity_prefix cannot be combined with pubkey");
        };
        if policy.issuer.as_deref().is_none_or(str::is_empty) {
            bail!("packslip: list_identity_prefix requires an issuer");
        }
        Ok(Self::Identity(Policy {
            issuer: policy.issuer.clone(),
            identity: None,
            identity_prefix: Some(prefix.to_string()),
        }))
    }

    fn trust(&self) -> Trust<'_> {
        match self {
            Pin::Identity(policy) => Trust::Identity(policy),
            Pin::Key(key) => Trust::Key(key),
        }
    }
}

/// Verify a bundle and, for each artifact path given, its digest and size.
/// Blocks: packslip drives sigstore on a runtime of its own.

View on GitHub (pinned to 533346cc37)