{"record":{"id":"640fd0e5e7eb4283","repo":"nats-io/nats-server","slug":"leafnode-v","errorCode":null,"errorMessage":"leafnode: %v","messagePattern":"leafnode: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/leafnode.go","lineNumber":352,"sourceCode":"\t\tif err := checkLeafMinVersionConfig(mv); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\t// The checks below will be done only when detecting that we are configured\n\t// with gateways. So if an option validation needs to be done regardless,\n\t// it MUST be done before this point!\n\n\tif o.Gateway.Name == _EMPTY_ && o.Gateway.Port == 0 {\n\t\treturn nil\n\t}\n\t// If we are here we have both leaf nodes and gateways defined, make sure there\n\t// is a system account defined.\n\tif o.SystemAccount == _EMPTY_ {\n\t\treturn fmt.Errorf(\"leaf nodes and gateways (both being defined) require a system account to also be configured\")\n\t}\n\tif err := validatePinnedCerts(o.LeafNode.TLSPinnedCerts); err != nil {\n\t\treturn fmt.Errorf(\"leafnode: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc checkLeafMinVersionConfig(mv string) error {\n\tif ok, err := versionAtLeastCheckError(mv, 2, 8, 0); !ok || err != nil {\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid leafnode's minimum version: %v\", err)\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"the minimum version should be at least 2.8.0\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// Used to validate user names in LeafNode configuration.\n// - rejects mix of single and multiple users.\n// - rejects duplicate user names.","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/leafnode.go#L334-L370","documentation":"This is a wrapping error emitted by validateLeafNode when validatePinnedCerts fails for the leafnode's TLSPinnedCerts. The original problem (an invalid pinned cert spec, e.g. malformed fingerprint or pubkey) is formatted as \"leafnode: %v\". It surfaces during Options validation whenever leaf node TLS pinned certificates are configured incorrectly.","triggerScenarios":"validateOptions -> validateLeafNode runs and validatePinnedCerts(o.LeafNode.TLSPinnedCerts) returns an error, i.e. the leafnode block contains tls_pinned_certs entries that fail validation (bad hex digest, unsupported format, empty entries).","commonSituations":"Operators hand-copy SHA-256 fingerprints with typos/extra characters, or use a cert format not supported by the pinned-cert validator, when hardening leaf node TLS connections.","solutions":["Read the wrapped inner error (the %v) to see why the pinned cert is invalid","Re-generate the pinned cert value, e.g. sha256 fingerprint of the peer cert, and paste it exactly (lowercase hex, no colons)","Remove the tls_pinned_certs entries if pinning is not required"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for _, c := range opts.LeafNode.TLSPinnedCerts {\n  if _, err := hex.DecodeString(c); err != nil || len(c) != 64 {\n    return fmt.Errorf(\"bad pinned cert %q: %v\", c, err)\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store fingerprints as lowercase hex without separators","Generate pinned cert values with `openssl x509 -fingerprint -sha256` and copy programmatically","Test pinned-cert configs with `nats-server -t` before rollout"],"tags":["leafnode","tls","pinned-certs","config-validation"],"backgroundTag":"tls-certificate-pinning-invalid","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}