jdx/mise · error

signature does not match any trusted public key

Error message

signature does not match any trusted public key

What it means

mise verifies downloaded archives against a detached GPG signature using a set of trusted public keys. After trying every candidate signature against every trusted key, if none verifies, verify_detached bails with this error. It means the artifact's signature could not be validated by any key mise trusts.

Solutions

  1. Re-download the artifact and its signature (delete the cached download and retry the install) — corruption is the most common cause.
  2. Verify the artifact's signing key against upstream key IDs and add/update trusted keys in the local key set if upstream rotated keys.
  3. Check that you're fetching artifacts from official sources, not a proxy that re-signs or re-packages them.
  4. Confirm the signature file is complete and matches the exact bytes being verified (same version/platform archive).

Example fix

// before: retrying against a corrupted cached download
mise install node@22.0.0   // fails: signature does not match any trusted public key
// after: clear the corrupt download cache and reinstall
rm -rf ~/.cache/mise/node/archive/v22.0.0* && mise install node@22.0.0
Defensive patterns

Strategy: validation

Validate before calling

# before install, verify the artifact+sig pair is intact
sig_bytes=$(curl -fsSL "$SIG_URL") && echo "signature fetched: ${#sig_bytes} bytes" || echo "signature missing/corrupt"

Prevention

When it happens

Trigger: Calling verify_detached (via verify_node, verify_swift, or verify_swift_bytes) on a downloaded file whose detached signature is invalid, signed by an untrusted/unknown key, corrupted in transit, or stripped of its issuer subpacket so it can't be matched to a key.

Common situations: Mirror or proxy serving a re-signed or tampered node/swift tarball; download truncation corrupting the .sig file; upstream changed signing keys while local trusted keys are stale; fetching a nightly/RC artifact that isn't signed the same way as releases.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/gpg.rs:63

        bail!("no signature found to verify");
    }

    // Fast path: only try keys whose id/fingerprint matches the signature's issuer, so the signed
    // content is hashed at most once in the common case.
    for sig in &signatures {
        if verify_against_keys(sig, &keys, &open_data, true)? {
            return Ok(());
        }
    }
    // Fallback: try every trusted key, but only for signatures that carried no usable issuer
    // hint. A signature that named an issuer we don't trust is genuinely unverifiable, so skip it
    // rather than re-hashing the (potentially large) content against every key.
    for sig in signatures.iter().filter(|sig| !has_issuer(&sig.signature)) {
        if verify_against_keys(sig, &keys, &open_data, false)? {
            return Ok(());
        }
    }
    bail!("signature does not match any trusted public key");
}

fn verify_against_keys<R, F>(
    sig: &DetachedSignature,
    keys: &[SignedPublicKey],
    open_data: &F,
    require_issuer_match: bool,
) -> Result<bool>
where
    R: Read,
    F: Fn() -> Result<R>,
{
    for key in keys {
        if (!require_issuer_match
            || issuer_matches(&sig.signature, &key.fingerprint(), &key.legacy_key_id()))
            && try_verify(sig, key, open_data)?
        {
            return Ok(true);

View on GitHub (pinned to 533346cc37)