hashicorp/nomad · error

start_block_for %v not a valid duration: %v

Error message

start_block_for %v not a valid duration: %v

What it means

The mock driver parses the task's StartBlockFor config value into a time.Duration during StartTask via parseDriverConfig. If the string is not a valid Go duration (e.g. "500" or "5x" instead of "5s"), parseDuration fails and the task cannot start, so this wrapped error is returned to the caller.

Source

Thrown at drivers/mock/driver.go:434

		return fmt.Errorf("stdout_repeat_duration %v not a valid duration: %v", c.stdoutRepeatDuration, err)
	}

	if c.stderrRepeatDuration, err = parseDuration(c.StderrRepeatDur); err != nil {
		return fmt.Errorf("stderr_repeat_duration %v not a valid duration: %v", c.stderrRepeatDuration, err)
	}

	return nil
}

func parseDriverConfig(cfg *drivers.TaskConfig) (*TaskConfig, error) {
	var driverConfig TaskConfig
	if err := cfg.DecodeDriverConfig(&driverConfig); err != nil {
		return nil, err
	}

	var err error
	if driverConfig.startBlockForDuration, err = parseDuration(driverConfig.StartBlockFor); err != nil {
		return nil, fmt.Errorf("start_block_for %v not a valid duration: %v", driverConfig.StartBlockFor, err)
	}

	if driverConfig.pluginExitAfterDuration, err = parseDuration(driverConfig.PluginExitAfter); err != nil {
		return nil, fmt.Errorf("plugin_exit_after %v not a valid duration: %v", driverConfig.PluginExitAfter, err)
	}

	if err = driverConfig.parseDurations(); err != nil {
		return nil, err
	}

	if driverConfig.ExecCommand != nil {
		if err = driverConfig.ExecCommand.parseDurations(); err != nil {
			return nil, err
		}
	}

	return &driverConfig, nil
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix the StartBlockFor value in the task's driver config to a valid Go duration string (e.g. "5s", "500ms").
  2. Ensure the value has an explicit unit suffix; bare integers are rejected by time.ParseDuration.
  3. Check the wrapped inner error in the message for the exact parse failure position.

Example fix

// before
config := map[string]interface{}{"StartBlockFor": "500"}
// after
config := map[string]interface{}{"StartBlockFor": "500ms"}
Defensive patterns

Strategy: validation

Validate before calling

if v, ok := cfg["StartBlockFor"].(string); !ok || v == "" {
    return errors.New("StartBlockFor must be a non-empty duration string")
} else if _, err := time.ParseDuration(v); err != nil {
    return fmt.Errorf("StartBlockFor %q is not a valid duration: %v", v, err)
}

Prevention

When it happens

Trigger: Calling StartTask with a MockDriverConfig whose StartBlockFor string is not parseable by Go's time.ParseDuration semantics (missing unit suffix, typo, empty string when non-empty is required).

Common situations: Typing StartBlockFor = "1000" meaning milliseconds instead of "1s"; copy-pasting durations from other systems that use "30m30s"-free bare numbers; job spec templates that interpolate an empty or malformed value.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


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