{"record":{"id":"7a75742a566cfd9e","repo":"netbirdio/netbird","slug":"invalid-key-id-w","errorCode":null,"errorMessage":"invalid key ID: %w","messagePattern":"invalid key ID: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/signer/revocation.go","lineNumber":143,"sourceCode":"\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 {\n\t\treturn fmt.Errorf(\"failed to write output files: %w\", err)\n\t}\n\n\tcmd.Println(\"✅ Revocation list extended successfully\")\n\treturn nil\n}\n\nfunc handleVerifyRevocationList(cmd *cobra.Command, revocationListFile, signatureFile, publicRootKeyFile string) error {\n\t// Read revocation list file\n\trlBytes, err := os.ReadFile(revocationListFile)","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/signer/revocation.go#L125-L161","documentation":"reposign.ParseKeyID rejected the --key-id value (client/internal/updater/reposign/key.go:51). A KeyID is the first 8 bytes of the SHA-256 of the Ed25519 public key, rendered as exactly 16 hex characters; create-root-key prints it as RootKey[ID=...]. The error is 'invalid KeyID length: got N, want 16 hex chars (8 bytes)' for any other length, or 'failed to decode KeyID' when non-hex characters are present.","triggerScenarios":"Passing the full 64-character SHA-256 hex; a 0x prefix; whitespace or a trailing newline picked up from terminal copy/paste; an odd-length string; uppercase is accepted but any non-hex character (g-z) is not.","commonSituations":"Copying the whole key fingerprint instead of the 16-char ID from the RootKey[...] line; scripting the flag from a variable that includes quotes or padding; a key ID from an incompatible system that uses different encodings.","solutions":["Extract exactly 16 hex characters: from RootKey[ID=1a2b3c4d5e6f7083, ...] take 1a2b3c4d5e6f7083","Strip any 0x prefix, surrounding quotes, and whitespace before passing the flag","Validate the shape before running: echo -n \"$KID\" | grep -qE '^[0-9a-fA-F]{16}$'","Cross-check against the id field inside the signer public key PEM's JSON body"],"exampleFix":"# before\nsigner extend-revocation-list --key-id 0x1a2b3c4d5e6f7080 --revocation-list-file rl.json --private-root-key root.pem\n# error: invalid key ID: invalid KeyID length: got 19, want 16 hex chars (8 bytes)\n\n# after\nsigner extend-revocation-list --key-id 1a2b3c4d5e6f7080 --revocation-list-file rl.json --private-root-key root.pem","handlingStrategy":"validation","validationCode":"var keyIDRe = regexp.MustCompile(`^[0-9a-fA-F]{16}$`)\n\nfunc normalizeKeyID(raw string) (string, error) {\n    s := strings.TrimSpace(raw)\n    s = strings.TrimPrefix(s, \"0x\")\n    if !keyIDRe.MatchString(s) {\n        return \"\", fmt.Errorf(\"key ID %q must be exactly 16 hex chars\", raw)\n    }\n    return s, nil\n}\n\n// kid, err := normalizeKeyID(keyIDFlag)\n// if err != nil { /* fail before calling the signer */ }","typeGuard":"func isValidKeyID(s string) bool {\n    return regexp.MustCompile(`^[0-9a-fA-F]{16}$`).MatchString(strings.TrimSpace(s))\n}","tryCatchPattern":null,"preventionTips":["Script key IDs through a regex gate: ^[0-9a-fA-F]{16}$","Copy IDs only from the RootKey[ID=...] line or the public key's id field","Trim shell-captured values to kill stray newlines and spaces"],"tags":["go","cli","validation","hex","revocation"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}