{"record":{"id":"5f3f8827847f5259","repo":"netbirdio/netbird","slug":"failed-to-read-revocation-list-file-w","errorCode":null,"errorMessage":"failed to read revocation list file: %w","messagePattern":"failed to read revocation list file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/revocation.go","lineNumber":133,"sourceCode":"\n\tcmd.Println(\"✅ Revocation list created successfully\")\n\treturn nil\n}\n\nfunc handleExtendRevocationList(cmd *cobra.Command, keyID, revocationListFile, privateRootKeyFile string) error {\n\tprivKeyPEM, err := os.ReadFile(privateRootKeyFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read private root key file: %w\", err)\n\t}\n\n\tprivateRootKey, err := reposign.ParseRootKey(privKeyPEM)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse private root key: %w\", err)\n\t}\n\n\trlBytes, err := os.ReadFile(revocationListFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read revocation list file: %w\", err)\n\t}\n\n\trl, err := reposign.ParseRevocationList(rlBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse revocation list: %w\", err)\n\t}\n\n\tkid, err := reposign.ParseKeyID(keyID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid key ID: %w\", err)\n\t}\n\n\tnewRLBytes, sigBytes, err := reposign.ExtendRevocationList(*privateRootKey, *rl, kid, expirationDuration)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to extend revocation list: %w\", err)\n\t}\n\n\tif err := writeOutputFiles(revocationListFile, revocationListFile+\".sig\", newRLBytes, sigBytes); err != nil {","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/revocation.go#L115-L151","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nsigner extend-revocation-list --key-id 1a2b3c4d5e6f7080 --revocation-list-file rl.json --private-root-key root.pem\n# error: failed to read revocation list file: open rl.json: no such file or directory\n\n# after\nsigner create-revocation-list --revocation-list-file rl.json --private-root-key root.pem\nsigner extend-revocation-list --key-id 1a2b3c4d5e6f7080 --revocation-list-file rl.json --private-root-key root.pem","handlingStrategy":"validation","validationCode":"func listExists(path string) bool {\n    info, err := os.Stat(path)\n    return err == nil && !info.IsDir() && info.Mode().Perm()&0o400 != 0\n}\n\n// if !listExists(revocationListFile) {\n//     // run create-revocation-list first, then extend\n// }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["go","cli","file-io","revocation","reposign"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}