jdx/mise · error

no signature found to verify

Error message

no signature found to verify

What it means

verify_detached parses the detached signature blob and throws this error when no signatures could be extracted from it. It guards against running an expensive verification pass on empty or non-signature data.

Source

Thrown at src/gpg.rs:45

/// `public_keys_asc` is one or more ASCII-armored public key blocks (a trusted keyring bundled
/// with mise). `open_data` returns a fresh reader over the signed content each time it is called,
/// so the content can be streamed (and, if necessary, re-read for another candidate key) without
/// buffering large files in memory.
///
/// Verification succeeds if any signature validates against any of the trusted keys or their
/// subkeys, mirroring `gpg --verify` against an imported keyring.
fn verify_detached<R, F>(public_keys_asc: &str, signature: &[u8], open_data: F) -> Result<()>
where
    R: Read,
    F: Fn() -> Result<R>,
{
    let keys = parse_public_keys(public_keys_asc)?;
    if keys.is_empty() {
        bail!("no trusted public keys available for verification");
    }
    let signatures = parse_signatures(signature)?;
    if signatures.is_empty() {
        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");

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Verify the signature file is the correct .sig/.asc companion to the downloaded artifact and is non-empty
  2. Re-download the signature file from the official release URL
  3. Check that the signature format matches what the parser expects (armored vs binary); fetch the other variant if one fails
  4. Confirm upstream did not change signature packaging in the release you are installing

Example fix

// before
let sig = std::fs::read("SHASUMS256.txt")?; // wrong file: checksum list, not a signature
verify_node(&archive, sig, keys)?;
// after
let sig = std::fs::read("SHASUMS256.txt.sig")?;
assert!(!sig.is_empty());
verify_node(&archive, sig, keys)?;
Defensive patterns

Strategy: validation

Validate before calling

let sig = std::fs::read(sig_path)?;
if sig.is_empty() {
    anyhow::bail!("signature file {} is empty", sig_path);
}
verify_node(&archive, sig, keys)?;

Prevention

When it happens

Trigger: Calling verify_node/verify_swift/verify_swift_bytes with a signature argument that parses to zero DetachedSignature entries — empty file, wrong file passed as the .sig, or a signature in a format the parser does not recognize.

Common situations: Downloaded a checksum file instead of the .sig file; signature file truncated to zero bytes by a failed download; upstream switched from ASCII-armored to binary signatures (or vice versa) so the parser finds nothing; passing the archive itself as the signature.

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/680fc3cd9f7df2f9. Report an issue: GitHub.