hashicorp/nomad · error

error parsing port %q from check %q: %v

Error message

error parsing port %q from check %q: %v

What it means

After splitting the check's PortLabel, the raw port string is converted with strconv.Atoi. When the host portion after the colon is not a numeric port (or is out of the valid range), Atoi fails and registration of the agent service is aborted with this message, wrapping the conversion error.

Source

Thrown at command/agent/consul/service_client.go:1273

			_ = c.agentAPI.ServiceDeregisterOpts(legacyID, nil)
		}

		for _, check := range service.Checks {
			checkID := MakeCheckID(id, check)
			if check.Type == structs.ServiceCheckScript {
				return fmt.Errorf("service %q contains invalid check: agent checks do not support scripts", service.Name)
			}
			checkHost, checkPort := serviceReg.Address, serviceReg.Port
			if check.PortLabel != "" {
				// Unlike tasks, agents don't use port labels. Agent ports are
				// stored directly in the PortLabel.
				host, rawport, err := net.SplitHostPort(check.PortLabel)
				if err != nil {
					return fmt.Errorf("error parsing port label %q from check %q: %v", service.PortLabel, check.Name, err)
				}
				port, err := strconv.Atoi(rawport)
				if err != nil {
					return fmt.Errorf("error parsing port %q from check %q: %v", rawport, check.Name, err)
				}
				checkHost, checkPort = host, port
			}
			checkReg, err := createCheckReg(id, checkID, check, checkHost, checkPort, "")
			if err != nil {
				return fmt.Errorf("failed to add check %q: %v", check.Name, err)
			}
			ops.regChecks = append(ops.regChecks, checkReg)
		}
	}

	// Don't bother committing agent checks if we're already shutting down
	c.agentLock.Lock()
	defer c.agentLock.Unlock()
	select {
	case <-c.shutdownCh:
		return nil
	default:

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Replace the non-numeric port with the actual numeric port in the check PortLabel (e.g. '127.0.0.1:4646')
  2. Check the wrapped Atoi error text for the offending value and fix typos
  3. If the port comes from a template, ensure the value is interpolated to a plain integer before the agent config loads
  4. Prefer omitting port_label so the check uses the service's registered port

Example fix

// before
port_label = "127.0.0.1:http"
// after
port_label = "127.0.0.1:4646"
Defensive patterns

Strategy: validation

Validate before calling

if _, port, err := net.SplitHostPort(check.PortLabel); err != nil {
  // split failed
} else if _, convErr := strconv.Atoi(port); convErr != nil {
  return fmt.Errorf("check %q port %q is not numeric", check.Name, port)
}

Type guard

func isNumericPort(label string) bool {
  _, port, err := net.SplitHostPort(label)
  if err != nil { return false }
  n, err := strconv.Atoi(port)
  return err == nil && n > 0 && n <= 65535
}

Prevention

When it happens

Trigger: A check PortLabel like '127.0.0.1:http' or '127.0.0.1:4646x' — SplitHostPort succeeds but the port component is non-numeric, so strconv.Atoi(rawport) errors and the wrapped message is returned.

Common situations: Using a service/port name instead of a number in an agent check port label; typo in the port; templating that left a placeholder like '${port}' unexpanded.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/0e6ab50616037535. Report an issue: GitHub.