hashicorp/nomad · error

malformed port map: %q

Error message

malformed port map: %q

What it means

StartTask converts the mock driver's DriverPortMap string into a single-entry port map by splitting on ":". If the string does not contain exactly one colon-separated pair (one label and one port), the port map is considered malformed and StartTask aborts.

Source

Thrown at drivers/mock/driver.go:482

	// Store last configs
	d.lastMu.Lock()
	d.lastDriverTaskConfig = cfg
	d.lastTaskConfig = driverConfig
	d.lastMu.Unlock()

	if driverConfig.StartErr != "" {
		return nil, nil, structs.NewRecoverableError(errors.New(driverConfig.StartErr), driverConfig.StartErrRecoverable)
	}

	// Create the driver network
	net := &drivers.DriverNetwork{
		IP:            driverConfig.DriverIP,
		AutoAdvertise: driverConfig.DriverAdvertise,
	}
	if raw := driverConfig.DriverPortMap; len(raw) > 0 {
		parts := strings.Split(raw, ":")
		if len(parts) != 2 {
			return nil, nil, fmt.Errorf("malformed port map: %q", raw)
		}
		port, err := strconv.Atoi(parts[1])
		if err != nil {
			return nil, nil, fmt.Errorf("malformed port map: %q -- error: %v", raw, err)
		}
		net.PortMap = map[string]int{parts[0]: port}
	}

	killCtx, killCancel := context.WithCancel(context.Background())
	h := &taskHandle{
		taskConfig:      cfg,
		command:         driverConfig.Command,
		execCommand:     driverConfig.ExecCommand,
		pluginExitAfter: driverConfig.pluginExitAfterDuration,
		killAfter:       driverConfig.killAfterDuration,
		logger:          d.logger.With("task_name", cfg.Name),
		waitCh:          make(chan interface{}),
		killCh:          killCtx.Done(),

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set DriverPortMap to a single "label:port" pair, e.g. "http:8080".
  2. Remove extra mappings or extra colons; only one port mapping is supported.
  3. Verify no whitespace or accidental characters split the value.

Example fix

// before
map[string]interface{}{"DriverPortMap": "http:8080,https:8443"}
// after
map[string]interface{}{"DriverPortMap": "http:8080"}
Defensive patterns

Strategy: validation

Validate before calling

raw, _ := cfg["DriverPortMap"].(string)
parts := strings.Split(raw, ":")
if len(parts) != 2 {
    return fmt.Errorf("DriverPortMap must be a single label:port pair, got %q", raw)
}

Prevention

When it happens

Trigger: DriverPortMap set to a string without exactly one colon: e.g. "web" (no colon), "web:8080:extra" (too many segments), or an empty string that still passed the len(raw) > 0 check.

Common situations: Users copying Docker-style multi-mapping syntax "8080:80,9090:90" which this driver does not support; trailing colons like "http:"; accidentally quoting or spacing the value.

Understand the failure class

Related errors


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