{"record":{"id":"7425123018cfc2fc","repo":"thanos-io/thanos","slug":"failed-to-parse-port-s-err-s","errorCode":null,"errorMessage":"failed to parse port: %s, err: %s","messagePattern":"failed to parse port: (.+?), err: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/discovery/memcache/resolver.go","lineNumber":105,"sourceCode":"\t}\n\n\tnodes, err := reader.ReadString('\\n')\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read nodes: %s\", err)\n\t}\n\n\tif len(configVersion)+len(nodes) != configSize {\n\t\treturn nil, fmt.Errorf(\"expected %d in config payload, but got %d instead\", configSize, len(configVersion)+len(nodes))\n\t}\n\n\tfor host := range strings.SplitSeq(strings.TrimSpace(nodes), \" \") {\n\t\tdnsIpPort := strings.Split(host, \"|\")\n\t\tif len(dnsIpPort) != 3 {\n\t\t\treturn nil, fmt.Errorf(\"node not in expected format: %s\", dnsIpPort)\n\t\t}\n\t\tport, err := strconv.Atoi(dnsIpPort[2])\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse port: %s, err: %s\", dnsIpPort, err)\n\t\t}\n\t\tclusterConfig.nodes = append(clusterConfig.nodes, node{dns: dnsIpPort[0], ip: dnsIpPort[1], port: port})\n\t}\n\n\treturn clusterConfig, nil\n}\n","sourceCodeStart":87,"sourceCodeEnd":112,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/discovery/memcache/resolver.go#L87-L112","documentation":"parseConfig validates each node record's third pipe-delimited field as the port and converts it with strconv.Atoi. This error is returned when that field is present (so the `dns|ip|port` shape is right) but is not a valid integer. It prevents a non-numeric port from entering the cluster config.","triggerScenarios":"Calling Resolve with a node token whose port field is non-numeric or empty-ish, e.g. \"mem1|10.0.0.1|memcache\" or \"mem1|10.0.0.1|\" style content that still yields 3 fields but where Atoi(dnsIpPort[2]) fails.","commonSituations":"Typos in config files (letters or symbols in the port field), placeholder text like `PORT` never substituted, or port fields pasted with surrounding whitespace that Atoi rejects.","solutions":["Correct the port field of the offending node record to a plain decimal integer (1-65535), e.g. `11211`.","Check the full error message: the wrapped strconv error names the exact string that failed to parse.","Validate the config with a script before deployment (split on space and '|', Atoi the third field).","Ensure template substitution actually replaced port placeholders in the generated config."],"exampleFix":"// before\n\"nodes\": \"mem1|10.0.0.1|http\"\n// after\n\"nodes\": \"mem1|10.0.0.1|11211\"","handlingStrategy":"validation","validationCode":"func validNodePorts(nodes string) error {\n\tfor host := range strings.SplitSeq(strings.TrimSpace(nodes), \" \") {\n\t\tparts := strings.Split(host, \"|\")\n\t\tif _, err := strconv.Atoi(parts[len(parts)-1]); err != nil {\n\t\t\treturn fmt.Errorf(\"bad port in %q: %w\", host, err)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never hand-edit port fields; use templates with integer-only placeholders.","Validate the port range 1-65535 during config generation.","Watch for whitespace around ports that strconv.Atoi rejects."],"tags":["go","config-parsing","port","strconv"],"backgroundTag":"invalid-config-value","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}