{"record":{"id":"82452b471cfb81b7","repo":"hashicorp/nomad","slug":"error-parsing-port-label-q-from-check-q-v","errorCode":null,"errorMessage":"error parsing port label %q from check %q: %v","messagePattern":"error parsing port label %q from check %q: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/consul/service_client.go","lineNumber":1269,"sourceCode":"\t\tlegacyID := service.LegacyAgentID(role)\n\t\tif legacyID != \"\" {\n\t\t\t// we intentionally swallow this error because these services likely\n\t\t\t// no longer exist\n\t\t\t_ = c.agentAPI.ServiceDeregisterOpts(legacyID, nil)\n\t\t}\n\n\t\tfor _, check := range service.Checks {\n\t\t\tcheckID := MakeCheckID(id, check)\n\t\t\tif check.Type == structs.ServiceCheckScript {\n\t\t\t\treturn fmt.Errorf(\"service %q contains invalid check: agent checks do not support scripts\", service.Name)\n\t\t\t}\n\t\t\tcheckHost, checkPort := serviceReg.Address, serviceReg.Port\n\t\t\tif check.PortLabel != \"\" {\n\t\t\t\t// Unlike tasks, agents don't use port labels. Agent ports are\n\t\t\t\t// stored directly in the PortLabel.\n\t\t\t\thost, rawport, err := net.SplitHostPort(check.PortLabel)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error parsing port label %q from check %q: %v\", service.PortLabel, check.Name, err)\n\t\t\t\t}\n\t\t\t\tport, err := strconv.Atoi(rawport)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error parsing port %q from check %q: %v\", rawport, check.Name, err)\n\t\t\t\t}\n\t\t\t\tcheckHost, checkPort = host, port\n\t\t\t}\n\t\t\tcheckReg, err := createCheckReg(id, checkID, check, checkHost, checkPort, \"\")\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to add check %q: %v\", check.Name, err)\n\t\t\t}\n\t\t\tops.regChecks = append(ops.regChecks, checkReg)\n\t\t}\n\t}\n\n\t// Don't bother committing agent checks if we're already shutting down\n\tc.agentLock.Lock()\n\tdefer c.agentLock.Unlock()","sourceCodeStart":1251,"sourceCodeEnd":1287,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/consul/service_client.go#L1251-L1287","documentation":"When registering an agent service, each non-empty check PortLabel is parsed with net.SplitHostPort to obtain host:port. This error wraps the SplitHostPort error (e.g. 'missing port in address' or 'too many colons in address') when the check's PortLabel is not a valid host:port pair. Unlike task services, agent checks must encode the port directly in the label, so any malformed value aborts registration.","triggerScenarios":"RegisterAgentWorkload with a check whose PortLabel is a bare port label (e.g. 'http') or otherwise lacks a 'host:port' form, so net.SplitHostPort returns an error; IPv6 literals not bracketed correctly also trigger 'too many colons'.","commonSituations":"Setting check.port_label = \"http\" (a task-style port label) in agent config where a raw 'host:port' like \"127.0.0.1:4646\" is required; copy-pasted task service config; forgetting the port entirely.","solutions":["Set the check's PortLabel to an explicit 'host:port' value, e.g. '127.0.0.1:4646', instead of a Nomad port label name","Check the wrapped %v error to distinguish 'missing port' (add :port) from 'too many colons' (bracket IPv6 like [::1]:4646)","Remove the port_label key entirely so the check inherits the service registration address/port","Audit other checks on the same agent service for the same malformed label"],"exampleFix":"// before (agent config)\ncheck {\n  type = \"http\"\n  port_label = \"http\"\n}\n// after\ncheck {\n  type = \"http\"\n  port_label = \"127.0.0.1:4646\"\n}","handlingStrategy":"validation","validationCode":"// Validate check port labels are host:port before applying agent config\n_, _, err := net.SplitHostPort(check.PortLabel)\nif err != nil {\n  return fmt.Errorf(\"check %q port_label %q must be host:port\", check.Name, check.PortLabel)\n}","typeGuard":"func isValidHostPort(label string) bool {\n  host, port, err := net.SplitHostPort(label)\n  return err == nil && host != \"\" && port != \"\"\n}","tryCatchPattern":null,"preventionTips":["Agent checks use raw host:port, not Nomad port labels — remember the difference","Bracket IPv6 literals: [::1]:4646","Test with `net.SplitHostPort` before deploying config","Omit port_label to inherit the service registration address"],"tags":["consul","nomad","port-label","config-parsing"],"backgroundTag":"invalid-port-label","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}