{"record":{"id":"0c7badb13283d5dd","repo":"netbirdio/netbird","slug":"failed-to-read-public-root-key-file-w","errorCode":null,"errorMessage":"failed to read public root key file: %w","messagePattern":"failed to read public root key file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/revocation.go","lineNumber":175,"sourceCode":"}\n\nfunc handleVerifyRevocationList(cmd *cobra.Command, revocationListFile, signatureFile, publicRootKeyFile string) error {\n\t// Read revocation list file\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\t// Read signature file\n\tsigBytes, err := os.ReadFile(signatureFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read signature file: %w\", err)\n\t}\n\n\t// Read public root key file\n\tpubKeyPEM, err := os.ReadFile(publicRootKeyFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read public root key file: %w\", err)\n\t}\n\n\t// Parse public root key\n\tpublicKey, err := reposign.ParseRootPublicKey(pubKeyPEM)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse public root key: %w\", err)\n\t}\n\n\t// Parse signature\n\tsignature, err := reposign.ParseSignature(sigBytes)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse signature: %w\", err)\n\t}\n\n\t// Validate revocation list\n\trl, err := reposign.ValidateRevocationList([]reposign.PublicKey{publicKey}, rlBytes, *signature)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to validate revocation list: %w\", err)","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/revocation.go#L157-L193","documentation":"os.ReadFile on the --public-root-key path failed in verify-revocation-list. This is a pure IO error raised before ParseRootPublicKey runs; the PathError text separates a missing file, a permission problem, or a directory path.","triggerScenarios":"verify-revocation-list with a --public-root-key path that does not exist, is unreadable, or is a directory; also triggered by passing the private key's path when only the public PEM was deployed to the verify host.","commonSituations":"The public key shipped with the verifier but installed under a different name; verifying in a container where the key was not mounted; a path typo after key rotation renamed files.","solutions":["Check the file exists and is readable: ls -l <path>","Ensure you pass the PUBLIC root key PEM (type ROOT PUBLIC KEY), not the private one","Mount or copy the public key to the verify host and re-run","Confirm the path after rotations — old and new keys often live side by side"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// verify flow: check the public key file before invoking the command\nif err := checkReadableFile(publicRootKeyFile); err != nil {\n    log.Fatalf(\"public root key unreadable: %v\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Deploy the public root key to verify hosts with the same pipeline as the lists","Name it explicitly (root-public.pem) to avoid confusion with the private half","Pin the path in config rather than passing ad-hoc flags"],"tags":["go","cli","file-io","key-management"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}