hashicorp/nomad · error

invalid hosts entry %q

Error message

invalid hosts entry %q

What it means

GenerateEtcHostsMount builds a synthetic /etc/hosts mount for a task. Each entry in the task's extra_hosts annotation must be of the form "hostname:IP"; it splits on the first colon and requires exactly two parts. An entry without a colon (or with more than one, though SplitN bounds it) produces this error.

Source

Thrown at drivers/shared/hostnames/mount.go:51

::1 localhost
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

# this entry is the IP address and hostname of the allocation
# shared with tasks in the task group's network
%s %s
`, hostsCfg.Address, hostsCfg.Hostname)

	if len(extraHosts) > 0 {
		content.WriteString("\n# these entries are extra hosts added by the task config")
		for _, hostLine := range extraHosts {
			hostsEntry := strings.SplitN(hostLine, ":", 2)
			if len(hostsEntry) != 2 {
				return nil, fmt.Errorf("invalid hosts entry %q", hostLine)
			}
			if net.ParseIP(hostsEntry[1]) == nil {
				return nil, fmt.Errorf("invalid IP address %q", hostLine)
			}
			content.WriteString(fmt.Sprintf("\n%s %s", hostsEntry[1], hostsEntry[0]))
		}
		content.WriteString("\n")
	}

	path := filepath.Join(taskDir, "hosts")

	// tasks within an alloc should be able to share and modify the file, so
	// only write to it if it doesn't exist
	if _, err := os.Stat(path); os.IsNotExist(err) {
		err := os.WriteFile(path, []byte(content.String()), 0644)
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix the task config so every extra_hosts entry is "hostname:IP", e.g. "myhost:192.168.1.10"
  2. Log or print the full extra_hosts list and find the entry lacking a colon
  3. Trim whitespace/empty entries from the list before submitting the job
  4. If generating the job from a template, validate the mapping produces colon-joined strings

Example fix

// before (job HCL)
extra_hosts = ["myhost"]
// after
extra_hosts = ["myhost:192.168.1.10"]
Defensive patterns

Strategy: validation

Validate before calling

func validExtraHosts(hosts []string) error {
    for _, h := range hosts {
        parts := strings.SplitN(h, ":", 2)
        if len(parts) != 2 { return fmt.Errorf("extra host %q must be hostname:IP", h) }
        if ip := net.ParseIP(parts[1]); ip == nil { return fmt.Errorf("extra host %q has invalid IP %q", h, parts[1]) }
    }
    return nil
}

Prevention

When it happens

Trigger: A task's ExtraHosts (docker --add-host equivalent) contains a string with no ":" separator, e.g. "myhost" instead of "myhost:192.168.1.10", passed through createContainerConfig when the driver sets up the container.

Common situations: Job authors typo the extra_hosts stanza (space instead of colon); copy Docker Compose syntax where mapping order/IP format differs; templating produces empty strings which split to one part; IPv6 addresses with colons confuse expectations when the hostname part is omitted.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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