netbirdio/netbird · error
failed to read signature file: %w
Error message
failed to read signature file: %w
What it means
os.ReadFile on the --signature-file path failed in verify-revocation-list. The signature is a separate JSON file (a Signature bundle: base64 signature bytes, timestamp, key_id, algorithm, hash_algo) that create-revocation-list and extend-revocation-list write next to the list as <list-path>.sig; verification needs both files from the same run.
Source
Thrown at client/cmd/signer/revocation.go:169
if err := writeOutputFiles(revocationListFile, revocationListFile+".sig", newRLBytes, sigBytes); err != nil {
return fmt.Errorf("failed to write output files: %w", err)
}
cmd.Println("✅ Revocation list extended successfully")
return nil
}
func handleVerifyRevocationList(cmd *cobra.Command, revocationListFile, signatureFile, publicRootKeyFile string) error {
// Read revocation list file
rlBytes, err := os.ReadFile(revocationListFile)
if err != nil {
return fmt.Errorf("failed to read revocation list file: %w", err)
}
// Read signature file
sigBytes, err := os.ReadFile(signatureFile)
if err != nil {
return fmt.Errorf("failed to read signature file: %w", err)
}
// Read public root key file
pubKeyPEM, err := os.ReadFile(publicRootKeyFile)
if err != nil {
return fmt.Errorf("failed to read public root key file: %w", err)
}
// Parse public root key
publicKey, err := reposign.ParseRootPublicKey(pubKeyPEM)
if err != nil {
return fmt.Errorf("failed to parse public root key: %w", err)
}
// Parse signature
signature, err := reposign.ParseSignature(sigBytes)
if err != nil {
return fmt.Errorf("failed to parse signature: %w", err)View on GitHub (pinned to 93e97f4bf1)
Solutions
- Fetch the matching .sig — it is written beside the list as <revocation-list-file>.sig at sign time
- Check for a rename: ls <dir> to see whether the signature survived under another name
- If the .sig is lost, regenerate the pair by re-running extend-revocation-list with the same key and list, then republish both
- Verify both files come from the same signing run — mixing list revisions with old signatures fails validation
Defensive patterns
Strategy: validation
Validate before calling
sigPath := revocationListFile + ".sig"
if _, err := os.Stat(sigPath); err != nil {
// signature companion missing: regenerate the pair with extend before verifying
log.Fatalf("signature %s missing: %v", sigPath, err)
} Prevention
- Treat <list>.sig as part of the list artifact, never as a separate file
- Exclude *.sig from cleanup rules and gitignore exceptions
- Regenerate both files together whenever either is lost
When it happens
Trigger: Verifying with only the list copied over while the .sig companion was left behind; passing the list path where the signature path is expected but with a typo in the .sig suffix; the .sig deleted by cleanup scripts that treat it as an unknown artifact.
Common situations: Artifact pipelines that publish the list but drop unknown *.sig files; operators renaming files for distribution; the .sig never committed because .gitignore excluded it.
Related errors
- failed to read revocation list file: %w
- failed to validate revocation list: %w
- failed to write signature file: %w
- revocation list verification failed
- failed to create artifact key: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/07415da1f7ed2ff2.
Report an issue: GitHub.