{"record":{"id":"680fc3cd9f7df2f9","repo":"jdx/mise","slug":"no-signature-found-to-verify","errorCode":null,"errorMessage":"no signature found to verify","messagePattern":"no signature found to verify","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/gpg.rs","lineNumber":45,"sourceCode":"/// `public_keys_asc` is one or more ASCII-armored public key blocks (a trusted keyring bundled\n/// with mise). `open_data` returns a fresh reader over the signed content each time it is called,\n/// so the content can be streamed (and, if necessary, re-read for another candidate key) without\n/// buffering large files in memory.\n///\n/// Verification succeeds if any signature validates against any of the trusted keys or their\n/// subkeys, mirroring `gpg --verify` against an imported keyring.\nfn verify_detached<R, F>(public_keys_asc: &str, signature: &[u8], open_data: F) -> Result<()>\nwhere\n    R: Read,\n    F: Fn() -> Result<R>,\n{\n    let keys = parse_public_keys(public_keys_asc)?;\n    if keys.is_empty() {\n        bail!(\"no trusted public keys available for verification\");\n    }\n    let signatures = parse_signatures(signature)?;\n    if signatures.is_empty() {\n        bail!(\"no signature found to verify\");\n    }\n\n    // Fast path: only try keys whose id/fingerprint matches the signature's issuer, so the signed\n    // content is hashed at most once in the common case.\n    for sig in &signatures {\n        if verify_against_keys(sig, &keys, &open_data, true)? {\n            return Ok(());\n        }\n    }\n    // Fallback: try every trusted key, but only for signatures that carried no usable issuer\n    // hint. A signature that named an issuer we don't trust is genuinely unverifiable, so skip it\n    // rather than re-hashing the (potentially large) content against every key.\n    for sig in signatures.iter().filter(|sig| !has_issuer(&sig.signature)) {\n        if verify_against_keys(sig, &keys, &open_data, false)? {\n            return Ok(());\n        }\n    }\n    bail!(\"signature does not match any trusted public key\");","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/gpg.rs#L27-L63","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the signature file is the correct .sig/.asc companion to the downloaded artifact and is non-empty","Re-download the signature file from the official release URL","Check that the signature format matches what the parser expects (armored vs binary); fetch the other variant if one fails","Confirm upstream did not change signature packaging in the release you are installing"],"exampleFix":"// before\nlet sig = std::fs::read(\"SHASUMS256.txt\")?; // wrong file: checksum list, not a signature\nverify_node(&archive, sig, keys)?;\n// after\nlet sig = std::fs::read(\"SHASUMS256.txt.sig\")?;\nassert!(!sig.is_empty());\nverify_node(&archive, sig, keys)?;","handlingStrategy":"validation","validationCode":"let sig = std::fs::read(sig_path)?;\nif sig.is_empty() {\n    anyhow::bail!(\"signature file {} is empty\", sig_path);\n}\nverify_node(&archive, sig, keys)?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm you pass the .sig/.asc companion file, not a checksum list or the archive","Check signature file size > 0 after download","If upstream switches signature format, re-fetch both artifact and signature together"],"tags":["gpg","signature","verification"],"backgroundTag":"empty-required-field","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}