Skip to content

Errors

Every exported sentinel error, grouped by package. All of them are wrapped with cockroachdb/errors, so match them with errors.Is and never by comparing message text.

Three different ErrUnsupportedKeyType sentinels

openpgpkey, local and minisign each declare their own ErrUnsupportedKeyType, and they are not the same value. A check written against the wrong package's sentinel silently never matches.

Sentinel Means
openpgpkey.ErrUnsupportedKeyType The signer's Public() is not *rsa.PublicKey. OpenPGP minting and detached signing here are RSA-only.
local.ErrUnsupportedKeyType The PEM file holds something other than RSA or Ed25519 — ECDSA, for instance.
minisign.ErrUnsupportedKeyType The signer's Public() is not ed25519.PublicKey. minisign is Ed25519-only.

Import the package whose function you called, and match that one.

signing — the registry

Sentinel Raised by Meaning and response
ErrUnknownBackend signing.Get No backend is registered under that name. The message lists the names that are registered, or says the binary "was built without any signing backends compiled in" when the registry is empty. Almost always a missing blank import.

signing.Register reports its failures by panicking, not by returning an error: a nil Backend, a Backend whose Name() is empty, or a duplicate name. All three are programming errors at process init, and failing at startup is preferred to a silently overridden backend. There is no way to unregister a backend outside tests.

verify — trust sets and resolvers

Sentinel Raised by Meaning and response
ErrSignatureInvalid TrustSet.VerifyManifestSignature, VerifyManifestSignatureSigner The signature is empty, malformed, or does not validate under any key in the set. Reject the release.
ErrWeakKey LoadTrustSet, and every resolver that builds on it A key failed the minimum-strength policy. Fix the key; do not lower the floor.
ErrKeyResolverMismatch CompositeResolver.Resolve Two successful resolvers returned different fingerprint sets. Treat as possible compromise of an anchor. Never reconcile it.
ErrKeyResolverUnavailable WKD fetches, CompositeResolver.Resolve A resolver could not produce a trust set: network failure, non-200 status, no key at either WKD URL, no returned key matching the address, or — with RequireAll — any child failure at all.
ErrWKDResponseTooLarge the WKD fetch The response body exceeded MaxWKDResponseSize. Returned bare, not wrapped.
ErrSignatureMissing nothing in this module Declared for downstream self-updaters that fetch release assets. This module never returns it.
ErrSignatureTooLarge nothing in this module Likewise declared for downstream use. MaxSignatureSize is not enforced here.

Why ErrSignatureInvalid covers so much

VerifyManifestSignature deliberately does not distinguish a forged signature from an unparseable one — for a caller's purposes they are the same answer, and the error does not name which key rejected the signature so that logging the sentinel leaks nothing about the trust set.

The same sentinel also covers cases decided inside go-crypto: a revoked primary key, a revoked primary identity, a revoked or expired signing subkey, an expired signature, an expired key, an unknown critical notation, and an RSA key below the strength floor (enforced a second time at verification through packet.Config.MinRSABits). Expiry is judged against the current clock at verification time.

The underlying go-crypto error is folded into the message rather than the error chain, so errors.Is against a go-crypto sentinel will not match. If you need to tell an expired key from a forgery, read the message text — and treat both as "do not trust" regardless.

What CompositeResolver does to child errors

With RequireAll: true, the first child error is re-wrapped as ErrKeyResolverUnavailable using the child's message text only. The child's own sentinel is not preserved in the chain, so a child that failed with ErrWeakKey surfaces as ErrKeyResolverUnavailable and errors.Is(err, verify.ErrWeakKey) returns false. The original wording is still in the message, prefixed with composite: resolver "<name>".

Errors with no sentinel

Some failures return a plain error with no sentinel to match on. Detect them by failing closed, not by string comparison:

  • LoadTrustSet: no keys provided, and per-key parse failures.
  • composite: no resolvers configured.
  • wkd: email is required, wkd: HTTPClient is required, wkd: invalid email …, and the domain-validation failures.
  • wkd: refusing non-HTTPS URL — raised before any request is made.
  • wkd: parsing key response — the WKD body was not a parseable binary keyring.
  • The key_source=… configuration errors listed in Configuration fields.

openpgpkey — minting and signing

Sentinel Raised by Meaning and response
ErrUnsupportedKeyType Entity, ArmoredPublicKey, WriteArmoredPublicKey, DetachSign The signer is not RSA. Use an RSA key for the OpenPGP path, or minisign for Ed25519 artefact signing.

DetachSign has three further failure modes that return plain errors, and each means something specific:

  • expected exactly one entity in armored public key, got N — the public key blob holds a keyring, not a single key.
  • armored public key has no User ID; cannot sign with an unidentified key — a bare public-key packet was passed instead of a self-signed key.
  • signer's RSA public half does not match the public key block — wrong key? — the signer and the published key are different keys. Signing anyway would produce a signature naming the published fingerprint that no verifier accepts.

WriteWKDTree returns plain errors for an empty entry list, an invalid domain, an unparseable Email or SubmissionAddress, an Entry with no keys, an invalid Method, or a key that parses as neither armoured nor binary OpenPGP.

local — the PEM backend

Sentinel Raised by Meaning and response
ErrMissingPEMBlock local.NewSigner The file decoded to no PEM block at all, or to a block whose type is neither RSA PRIVATE KEY nor PRIVATE KEY. The message names the path or the offending block type.
ErrEncryptedPEMUnsupported local.NewSigner The block type is ENCRYPTED PRIVATE KEY. Decrypt out of band first, or use a KMS backend.
ErrUnsupportedKeyType local.NewSigner The PKCS#8 blob parsed but holds neither an RSA nor an Ed25519 key. The message names the concrete type.

A missing or unreadable file surfaces as a wrapped os error under reading PEM file, not as a sentinel.

minisign — artefact signatures

Sentinel Raised by Meaning and response
ErrUnsupportedKeyType SignDigest (so also Sign) The signer's public half is not Ed25519. An RSA KMS key cannot produce minisign signatures.
ErrUnsupportedAlgorithm VerifyDigest (so also Verify, VerifyFile) The signature carries a tag other than the prehashed "ED" — usually a legacy pure "Ed" signature. cargo-binstall rejects those too.
ErrMalformedSignature ParseSignature, SignDigest, VerifyDigest The file lacks its four fields, a base64 body will not decode, a body is the wrong length, or a supplied digest is not 64 bytes.
ErrMalformedPublicKey NewPublicKey, ParsePublicKey, VerifyDigest The key is not 32 bytes, no base64 body was found, or the decoded body is the wrong length.
ErrKeyIDMismatch VerifyDigest The signature names a different key. Checked before any signature maths runs.
ErrBadSignature VerifyDigest The artefact signature does not verify under the key. Reject the artefact.
ErrBadGlobalSignature VerifyDigest The artefact signature verified but the global signature did not — the trusted comment has been tampered with. Reject the artefact.
ErrInvalidComment PublicKey.File, SignDigest A comment contains a carriage return or newline, which would corrupt the line-oriented format and could forge extra fields.
ErrCommentTooLong PublicKey.File, SignDigest A comment exceeds the reference implementation's limit. The Rust verifiers do not enforce these limits, so without this check an over-long comment would pass every test here and fail against upstream minisign -V.
ErrSignerOutput SignDigest The signer returned something other than a raw 64-byte Ed25519 signature — a DER-wrapped value, for instance. Both Rust consumers require the raw form.