netbirdio/netbird · error
failed to read revocation list file: %w
Error message
failed to read revocation list file: %w
What it means
os.ReadFile on the --revocation-list-file path failed inside extend-revocation-list. Extend mutates an existing signed list (it adds the key ID and re-signs), so the file must already exist and be readable; the most common cause is that no list has been created yet.
Source
Thrown at client/cmd/signer/revocation.go:133
cmd.Println("✅ Revocation list created successfully")
return nil
}
func handleExtendRevocationList(cmd *cobra.Command, keyID, revocationListFile, privateRootKeyFile string) error {
privKeyPEM, err := os.ReadFile(privateRootKeyFile)
if err != nil {
return fmt.Errorf("failed to read private root key file: %w", err)
}
privateRootKey, err := reposign.ParseRootKey(privKeyPEM)
if err != nil {
return fmt.Errorf("failed to parse private root key: %w", err)
}
rlBytes, err := os.ReadFile(revocationListFile)
if err != nil {
return fmt.Errorf("failed to read revocation list file: %w", err)
}
rl, err := reposign.ParseRevocationList(rlBytes)
if err != nil {
return fmt.Errorf("failed to parse revocation list: %w", err)
}
kid, err := reposign.ParseKeyID(keyID)
if err != nil {
return fmt.Errorf("invalid key ID: %w", err)
}
newRLBytes, sigBytes, err := reposign.ExtendRevocationList(*privateRootKey, *rl, kid, expirationDuration)
if err != nil {
return fmt.Errorf("failed to extend revocation list: %w", err)
}
if err := writeOutputFiles(revocationListFile, revocationListFile+".sig", newRLBytes, sigBytes); err != nil {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Create the initial list first: signer create-revocation-list --revocation-list-file <path> --private-root-key <key>
- Verify the path and its readability: ls -l <path>
- Fetch/restore the current list from wherever it is published before extending
- Never hand-write the JSON from scratch — create it with the tool so the companion .sig exists
Example fix
# before signer extend-revocation-list --key-id 1a2b3c4d5e6f7080 --revocation-list-file rl.json --private-root-key root.pem # error: failed to read revocation list file: open rl.json: no such file or directory # after signer create-revocation-list --revocation-list-file rl.json --private-root-key root.pem signer extend-revocation-list --key-id 1a2b3c4d5e6f7080 --revocation-list-file rl.json --private-root-key root.pem
Defensive patterns
Strategy: validation
Validate before calling
func listExists(path string) bool {
info, err := os.Stat(path)
return err == nil && !info.IsDir() && info.Mode().Perm()&0o400 != 0
}
// if !listExists(revocationListFile) {
// // run create-revocation-list first, then extend
// } Prevention
- Bootstrap new environments with create-revocation-list before any extend step
- Keep the current list at a stable path in versioned storage
- Automate fetch-then-extend in release scripts so the list is always present
When it happens
Trigger: Running extend-revocation-list before ever running create-revocation-list; a typo in the path; a list file owned by another user or with no read permission; the path naming a directory.
Common situations: New signer setup where the operator skips the create step; CI job that extends a list never fetched from storage; list stored beside keys under root ownership while running as another user.
Related errors
- failed to write output files: %w
- failed to parse revocation list: %w
- failed to read signature file: %w
- failed to create artifact key: %w
- read root private key file: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/5f3f8827847f5259.
Report an issue: GitHub.