{"record":{"id":"f32950c90e19586e","repo":"netbirdio/netbird","slug":"read-revocation-file-w","errorCode":null,"errorMessage":"read revocation file: %w","messagePattern":"read revocation file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/artifactsign.go","lineNumber":238,"sourceCode":"\t}\n\n\t// Read signature\n\tsigBytes, err := os.ReadFile(signatureFile)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read signature file: %w\", err)\n\t}\n\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// Read optional revocation list\n\tvar revocationList *reposign.RevocationList\n\tif revocationFile != \"\" {\n\t\trevData, err := os.ReadFile(revocationFile)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"read revocation file: %w\", err)\n\t\t}\n\n\t\trevocationList, err = reposign.ParseRevocationList(revData)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to parse revocation list: %w\", err)\n\t\t}\n\t}\n\n\t// Validate artifact key(s)\n\tvalidKeys, err := reposign.ValidateArtifactKeys(rootPublicKeys, artifactKeyData, *signature, revocationList)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"artifact key verification failed: %w\", err)\n\t}\n\n\tcmd.Println(\"✅ Artifact key(s) verified successfully\")\n\tcmd.Printf(\"Signed by root key: %s\\n\", signature.KeyID)\n\tcmd.Printf(\"Signature timestamp: %s\\n\", signature.Timestamp.Format(\"2006-01-02 15:04:05 MST\"))\n\tcmd.Printf(\"\\nValid artifact keys (%d):\\n\", len(validKeys))","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/artifactsign.go#L220-L256","documentation":"os.ReadFile on the optional --revocation-file path failed during verify-artifact-key. The flag is optional: omitting it skips revocation checking entirely, but once provided the file must be readable, otherwise the command aborts before ValidateArtifactKeys runs.","triggerScenarios":"Revocation list JSON not yet downloaded when the flag is set; typo in the path; passing the .sig of the revocation list instead of the list itself.","commonSituations":"Verification scripts always pass --revocation-file even on hosts where the list has not been provisioned; the list exists only on the update-key CDN.","solutions":["ls -l the exact --revocation-file value and fix the path","Download the published revocation-list.json before verifying","If revocation checking is not needed for this run, omit the flag"],"exampleFix":"// before\n--revocation-file revocation-list.json.sig\n\n// after\n--revocation-file revocation-list.json","handlingStrategy":"validation","validationCode":"if revocationFile != \"\" {\n    if _, err := os.Stat(revocationFile); err != nil {\n        log.Fatalf(\"revocation file %s not readable: %v\", revocationFile, err)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only set --revocation-file when revocation checking is actually required and the list is provisioned","Download revocation-list.json from the canonical key store, never hand-place it"],"tags":["go","cli","filesystem","release-signing"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}