hashicorp/nomad · error

invalid address '%s': %v

Error message

invalid address '%s': %v

What it means

In api/api.go:524, NewClient parses Config.Address with net/url.Parse before first use (also testing NOMAD_ADDR-derived defaults). If the address string is not a valid URL, NewClient fails with this error wrapping the url.Parse message. It is a configuration error — the client never issues any request.

Source

Thrown at api/api.go:524

}

// NewClient returns a new client
func NewClient(config *Config) (*Client, error) {
	var err error
	// bootstrap the config
	defConfig := DefaultConfig()

	if config.Address == "" {
		config.Address = defConfig.Address
	}

	// we have to test the address that comes from DefaultConfig, because it
	// could be the value of NOMAD_ADDR which is applied without testing. But
	// only on the first use of this Config, otherwise we'll have mutated the
	// address
	if config.url == nil {
		if config.url, err = url.Parse(config.Address); err != nil {
			return nil, fmt.Errorf("invalid address '%s': %v", config.Address, err)
		}
	}

	httpClient := config.HttpClient
	if httpClient == nil {
		switch {
		case config.url.Scheme == "unix":
			httpClient = defaultUDSClient(config) // mutates config
		default:
			httpClient = defaultHttpClient()
		}

		if err := ConfigureTLS(httpClient, config.TLSConfig); err != nil {
			return nil, err
		}
	}

	client := &Client{

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Read the wrapped %v message for the exact parse failure and fix the Address string
  2. Ensure the address includes a scheme, e.g. http://127.0.0.1:4646 or https://nomad.example.com
  3. Echo/inspect NOMAD_ADDR for whitespace, newlines, or stray characters; re-export it
  4. Wrap IPv6 literals in square brackets: http://[::1]:4646
  5. Validate the URL with url.Parse in your own bootstrap code before calling NewClient

Example fix

// before
cfg.Address := os.Getenv("NOMAD_ADDR") // "http://nomad.internal :4646"
client, err := api.NewClient(cfg) // invalid address
// after
addr := strings.TrimSpace(os.Getenv("NOMAD_ADDR"))
if _, err := url.Parse(addr); err != nil { return fmt.Errorf("bad NOMAD_ADDR %q: %w", addr, err) }
cfg.Address = addr
Defensive patterns

Strategy: validation

Validate before calling

addr := strings.TrimSpace(os.Getenv("NOMAD_ADDR"))
if u, err := url.Parse(addr); err != nil || u.Scheme == "" || u.Host == "" {
	return fmt.Errorf("NOMAD_ADDR must be a full URL like http://127.0.0.1:4646, got %q", addr)
}

Type guard

func validAddress(addr string) bool {
	u, err := url.Parse(addr)
	return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}

Try / catch

client, err := api.NewClient(cfg)
if err != nil && strings.Contains(err.Error(), "invalid address") {
	return fmt.Errorf("check NOMAD_ADDR/Config.Address: %w", err)
}

Prevention

When it happens

Trigger: Constructing api.NewClient(&api.Config{Address: "..."}) or setting NOMAD_ADDR to a string url.Parse rejects: control characters, malformed schemes (e.g. "http://[bad-ipv6"), stray spaces, or an empty/garbage value.

Common situations: NOMAD_ADDR exported with trailing whitespace or a typo; templating tools injecting multi-line values; concatenating host:port strings incorrectly; IPv6 addresses missing brackets.

Related errors


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