hashicorp/nomad · error

error determining port: %v

Error message

error determining port: %v

What it means

apiToCurl builds an equivalent curl command for `nomad operator api`. When a TLSServerName is configured, it splits the URL host with net.SplitHostPort to rewire the host for curl's --connect-to flag; if the host component is not in host:port form (or is malformed), SplitHostPort fails and the error is surfaced as "error determining port: %v".

Source

Thrown at command/operator_api.go:335

	}

	if c.body != nil {
		parts = append(parts, "--data-binary @-")
	}

	if config.URL().EscapedPath() != "" {
		parts = append(parts, fmt.Sprintf("--unix-socket %q", config.URL().EscapedPath()))
	}

	if config.TLSConfig != nil {
		parts = tlsToCurl(parts, config.TLSConfig)

		// If a TLS server name is set we must alter the URL and use
		// curl's --connect-to flag.
		if v := config.TLSConfig.TLSServerName; v != "" {
			pathHost, port, err := net.SplitHostPort(path.Host)
			if err != nil {
				return "", fmt.Errorf("error determining port: %v", err)
			}

			// curl uses the url for SNI so override it with the
			// configured server name
			path.Host = net.JoinHostPort(v, port)

			// curl uses --connect-to to allow specifying a
			// different connection address for the hostname in the
			// path. The format is:
			//   logical-host:logical-port:actual-host:actual-port
			// Ports will always match since only the hostname is
			// overridden for SNI.
			parts = append(parts, fmt.Sprintf(`--connect-to "%s:%s:%s:%s"`,
				v, port, pathHost, port))
		}
	}

	// Add headers

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Include an explicit port in NOMAD_ADDR/config.Address (e.g. https://host:4646).
  2. Wrap IPv6 hosts in brackets: http://[::1]:4646.
  3. Remove stray path/scheme characters from the address so url.Parse yields a clean Host.
  4. If you don't need SNI override, unset tls.server_name.

Example fix

// before (shell)
NOMAD_ADDR=https://nomad.internal nomad operator api /v1/health   # TLSServerName set, no port
// after
NOMAD_ADDR=https://nomad.internal:4647 nomad operator api /v1/health
Defensive patterns

Strategy: validation

Validate before calling

// shell: ensure address has host:port before operator api
case "$(echo "$NOMAD_ADDR" | sed -E 's#^https?://([^/]+)/?.*#\1#')" in
  *:*) : ;;  # ok
  *) echo "NOMAD_ADDR must include an explicit port when tls.server_name is set"; exit 1 ;;
esac

Try / catch

// bash
if ! out=$(nomad operator api /v1/health 2>&1); then
  case "$out" in *"error determining port"*) echo "fix NOMAD_ADDR host:port" ;; esac
fi

Prevention

When it happens

Trigger: `nomad operator api <path>` with a client config that sets tls.server_name (or NOMAD_CACERT/TLS server name) and an Address/URL whose host part lacks a port or contains malformed brackets, e.g. `https://nomad.example.com/path` without an explicit port or a bare IPv6 string without brackets.

Common situations: Address configured without :port while TLSServerName set; mis-entered IPv6 address missing brackets; environment variable NOMAD_ADDR containing a path or extra characters; config file mixing TLS options with a non-authority URL.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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