{"record":{"id":"c11f2a2a9f3afa36","repo":"slackhq/nebula","slug":"failed-to-decode-issuer-w","errorCode":null,"errorMessage":"failed to decode issuer: %w","messagePattern":"failed to decode issuer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cert/cert_v2.go","lineNumber":554,"sourceCode":"\n\t\t// Add IsCA only if true\n\t\tif d.isCA {\n\t\t\tb.AddASN1(TagDetailsIsCA, func(b *cryptobyte.Builder) {\n\t\t\t\tb.AddUint8(0xff)\n\t\t\t})\n\t\t}\n\n\t\t// Add not before\n\t\tb.AddASN1Int64WithTag(d.notBefore.Unix(), TagDetailsNotBefore)\n\n\t\t// Add not after\n\t\tb.AddASN1Int64WithTag(d.notAfter.Unix(), TagDetailsNotAfter)\n\n\t\t// Add the issuer if present\n\t\tif d.issuer != \"\" {\n\t\t\tissuerBytes, innerErr := hex.DecodeString(d.issuer)\n\t\t\tif innerErr != nil {\n\t\t\t\terr = fmt.Errorf(\"failed to decode issuer: %w\", innerErr)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tb.AddASN1(TagDetailsIssuer, func(b *cryptobyte.Builder) {\n\t\t\t\tb.AddBytes(issuerBytes)\n\t\t\t})\n\t\t}\n\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn b.Bytes()\n}\n\nfunc unmarshalCertificateV2(b []byte, publicKey []byte, curve Curve) (*certificateV2, error) {\n\tl := len(b)\n\tif l == 0 || l > MaxCertificateSize {","sourceCodeStart":536,"sourceCodeEnd":572,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/cert/cert_v2.go#L536-L572","documentation":"When marshalling certificate details, the Issuer field (if set) must be a hex-encoded string; it is hex-decoded so the raw bytes can be embedded in the ASN.1 structure. If hex.DecodeString fails, this error is returned. It means the Issuer string contains non-hex characters or odd length.","triggerScenarios":"Creating or signing a certificate whose details.issuer is set to a non-hex string (e.g. a raw fingerprint with separators, base64, or the full certificate text instead of hex of the issuer certificate's raw bytes).","commonSituations":"Setting Issuer = issuerCert.Details.Name or some human-readable ID instead of hex.EncodeToString(issuerRaw); copying a fingerprint formatted with colons; storing issuer via JSON round-trip that altered the string.","solutions":["Set the issuer using hex.EncodeToString of the signing certificate's raw bytes.","Strip non-hex characters (colons, whitespace) from any issuer string before assigning it.","Validate with hex.DecodeString yourself before building the certificate to fail early."],"exampleFix":"// before\ncertDetails.Issuer = string(signingCert.Raw()) // not hex\n// after\ncertDetails.Issuer = hex.EncodeToString(signingCert.Raw())","handlingStrategy":"validation","validationCode":"if details.Issuer != \"\" {\n    if _, err := hex.DecodeString(details.Issuer); err != nil {\n        return fmt.Errorf(\"issuer %q is not valid hex: %w\", details.Issuer, err)\n    }\n}","typeGuard":"func isHexString(s string) bool {\n    _, err := hex.DecodeString(s)\n    return err == nil && len(s)%2 == 0\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to decode issuer\") {\n    return fmt.Errorf(\"issuer must be hex-encoded raw certificate bytes: %w\", err)\n}","preventionTips":["Set Issuer only with hex.EncodeToString(issuerCert.Raw()).","Strip colons/whitespace from fingerprints before assignment.","Never store human-readable names in the Issuer field."],"tags":["certificate","hex","issuer","marshalling"],"backgroundTag":"invalid-hex-encoding","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}