{"record":{"id":"d810149353e0f235","repo":"netbirdio/netbird","slug":"failed-to-create-revocation-list-w","errorCode":null,"errorMessage":"failed to create revocation list: %w","messagePattern":"failed to create revocation list: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/revocation.go","lineNumber":109,"sourceCode":"\tif err := verifyRevocationListCmd.MarkFlagRequired(\"public-root-key\"); err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc handleCreateRevocationList(cmd *cobra.Command, revocationListFile string, 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, sigBytes, err := reposign.CreateRevocationList(*privateRootKey, expirationDuration)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create revocation list: %w\", err)\n\t}\n\n\tif err := writeOutputFiles(revocationListFile, revocationListFile+\".sig\", rlBytes, sigBytes); err != nil {\n\t\treturn fmt.Errorf(\"failed to write output files: %w\", err)\n\t}\n\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 {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/revocation.go#L91-L127","documentation":"Returned by the create-revocation-list command when reposign.CreateRevocationList fails (client/internal/updater/reposign/revocation.go:155). That function builds an empty RevocationList, signs it with the already-parsed Ed25519 root key, then json.Marshal's the list and the Signature bundle. Every input has been validated by ParseRootKey at this point, and Go's encoder always handles time.Time and KeyID, so the wrapped marshal/sign errors are internal invariant failures rather than configuration problems.","triggerScenarios":"Running `signer create-revocation-list` where os.ReadFile and reposign.ParseRootKey both succeeded, but json.Marshal(&rl) or json.Marshal(signature) inside CreateRevocationList returns an error, e.g. after someone forked reposign and added a field json.Marshal cannot encode (func, channel, cyclic pointer).","commonSituations":"Essentially never fires with stock code. Appears when the reposign package was modified (custom RevocationList/Signature fields) or under runtime-level anomalies; the %w chain names the exact failing step (sign / marshal list / marshal signature).","solutions":["Read the wrapped %w error to identify which internal step failed (failed to sign / failed to marshal revocation list / failed to marshal signature)","Re-run the command once to rule out a transient runtime fault","If reproducible, diff client/internal/updater/reposign/revocation.go against upstream and revert custom field changes to RevocationList or Signature","Report upstream with the full error chain if unmodified code produces it"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, _, err := reposign.CreateRevocationList(*privateRootKey, expiration); err != nil {\n    // internal invariant failure: log the full chain and abort; do not retry blindly\n    return fmt.Errorf(\"create revocation list: %w\", err)\n}","preventionTips":["Treat any failure from CreateRevocationList after a successful ParseRootKey as a code defect, not a config issue","Keep reposign unmodified or regression-test custom RevocationList/Signature fields with json.Marshal in unit tests","Log the wrapped chain verbatim so the failing marshal step is identifiable"],"tags":["go","cli","reposign","json","internal-invariant"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}