{"record":{"id":"76cc29d05414237c","repo":"cilium/cilium","slug":"addrcluster-unmarshaljson-bad-address","errorCode":null,"errorMessage":"AddrCluster.UnmarshalJSON: bad address","messagePattern":"AddrCluster\\.UnmarshalJSON: bad address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/clustermesh/types/addressing.go","lineNumber":48,"sourceCode":"// (e.g. network endpoint has a unique IP address). We can consider\n// this as a special case that ClusterID \"doesn't matter\". ClusterID\n// 0 is reserved for indicating that.\n//\n\n// AddrCluster is a type that holds a pair of IP and ClusterID.\n// We should use this type as much as possible when we implement\n// IP + Cluster addressing. We should avoid managing IP and ClusterID\n// separately. Otherwise, it is very hard for code readers to see\n// where we are using cluster-aware addressing.\ntype AddrCluster struct {\n\taddr      netip.Addr\n\tclusterID uint32\n}\n\nconst AddrClusterLen = 20\n\nvar (\n\terrUnmarshalBadAddress   = errors.New(\"AddrCluster.UnmarshalJSON: bad address\")\n\terrMarshalInvalidAddress = errors.New(\"AddrCluster.MarshalJSON: invalid address\")\n\n\tjsonZeroAddress = []byte(\"\\\"\\\"\")\n)\n\n// MarshalJSON marshals the address as a string in the form\n// <addr>@<clusterID>, e.g. \"1.2.3.4@1\"\nfunc (a *AddrCluster) MarshalJSON() ([]byte, error) {\n\tif !a.addr.IsValid() {\n\t\tif a.clusterID != 0 {\n\t\t\treturn nil, errMarshalInvalidAddress\n\t\t}\n\n\t\t// AddrCluster{} is the zero value. Preserve this across the\n\t\t// marshalling by returning an empty string.\n\t\treturn jsonZeroAddress, nil\n\t}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/clustermesh/types/addressing.go#L30-L66","documentation":"AddrCluster is Cilium's cluster-aware address type holding an IP plus optional ClusterID, serialized as \"<addr>@<clusterID>\" (e.g. \"1.2.3.4@1\"). UnmarshalJSON returns errUnmarshalBadAddress when the JSON value is not a quoted string of the expected form — e.g. unquoted input, empty string content, or missing surrounding quotes. The package then delegates to ParseAddrCluster, which yields a more specific parse error for malformed IP/clusterID content.","triggerScenarios":"Calling json.Unmarshal (directly or via a struct containing an AddrCluster field) with a JSON value that is not a double-quoted string: a number, an object, or a bare token; or a quoted string of length 0 (\"\"). Strings with content go to ParseAddrCluster, so only empty/non-string JSON triggers this exact error.","commonSituations":"Hand-editing cluster config/StateStore JSON where an address was written unquoted (e.g. 1.2.3.4@1 without quotes); tools emitting a number instead of a string for an IP field; passing an empty string \"\" for an address that should have been omitted.","solutions":["Wrap the address value in double quotes in the JSON, in the form \"<ip>@<clusterID>\" or a bare quoted IP like \"1.2.3.4\"","Ensure the value is not the empty string \"\" — omit the field or use the zero address representation \"\" only for AddrCluster{}","Validate with types.ParseAddrCluster(s) before marshaling the JSON to get a precise parse error","Check the JSON producer: a templating/script step may be dropping the quotes"],"exampleFix":"// before\n{\"addresses\": [1.2.3.4@1]}\n// after\n{\"addresses\": [\"1.2.3.4@1\"]}","handlingStrategy":"validation","validationCode":"func validAddrClusterJSON(b []byte) bool {\n\treturn len(b) > 2 && b[0] == '\"' && b[len(b)-1] == '\"'\n}\n// or pre-validate the string form:\nif _, err := types.ParseAddrCluster(s); err != nil { /* fix before encoding */ }","typeGuard":"func isJSONString(data []byte) bool {\n\treturn len(data) >= 2 && data[0] == '\"' && data[len(data)-1] == '\"'\n}","tryCatchPattern":"var ac types.AddrCluster\nif err := json.Unmarshal(data, &ac); err != nil {\n\tif errors.Is(err, types.ErrUnmarshalBadAddress) { // or strings.Contains\n\t\tlog.Warnf(\"skipping bad address payload %q\", data)\n\t\treturn nil // or surface a remediation hint\n\t}\n\treturn err\n}","preventionTips":["Always emit addresses as quoted strings \"<ip>@<id>\"; never rely on tools that drop JSON quotes","Unit-test JSON round-trips of AddrCluster values","Use ParseAddrCluster to validate address strings at config load time"],"tags":["go","json","unmarshal","cilium","clustermesh"],"backgroundTag":"json-unmarshal-invalid-address","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}