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
- Fix the StartBlockFor value in the task's driver config to a valid Go duration string (e.g. "5s", "500ms").
- Ensure the value has an explicit unit suffix; bare integers are rejected by time.ParseDuration.
- 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
- Always include a unit suffix in duration config strings ("5s", not "5").
- Run a local time.ParseDuration check in CI over job templates that inject durations.
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
- plugin_exit_after %v not a valid duration: %v
- error parsing rpc_handshake_timeout: %v
- start_timeout should be greater than 0s
- Error parsing max kill timeout: %s
- run_for %v not a valid duration: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/2b40b255753ead60.
Report an issue: GitHub.