hashicorp/nomad · error
stdout_repeat_duration %v not a valid duration: %v
Error message
stdout_repeat_duration %v not a valid duration: %v
What it means
parseDurations also converts StdoutRepeatDur into stdoutRepeatDuration using parseDuration. A value time.ParseDuration (or the mock helper) cannot interpret makes the driver return 'stdout_repeat_duration %v not a valid duration: %v'. Called from RecoverTask and parseDriverConfig, so it blocks both recovery and start of the mock task.
Source
Thrown at drivers/mock/driver.go:416
startedAt: taskState.StartedAt,
kill: killCancel,
killCh: killCtx.Done(),
Recovered: true,
}
d.tasks.Set(handle.Config.ID, h)
go h.run()
return nil
}
func (c *Command) parseDurations() error {
var err error
if c.runForDuration, err = parseDuration(c.RunFor); err != nil {
return fmt.Errorf("run_for %v not a valid duration: %v", c.RunFor, err)
}
if c.stdoutRepeatDuration, err = parseDuration(c.StdoutRepeatDur); err != nil {
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)View on GitHub (pinned to 482b49bf1a)
Solutions
- Set stdout_repeat_duration to a valid Go duration string, e.g. "1s", "500ms", "0".
- Read the wrapped time.ParseDuration error to see the offending substring.
- Validate interpolated values before submitting the job (nomad job inspect / local validation).
- For recovery failures, resubmit the job with corrected config.
Example fix
// before stdout_repeat_duration = "500" // after stdout_repeat_duration = "500ms"
Defensive patterns
Strategy: validation
Validate before calling
if _, err := time.ParseDuration(c.StdoutRepeatDur); err != nil {
return fmt.Errorf("stdout_repeat_duration must be like 500ms, got %q", c.StdoutRepeatDur)
} Type guard
func validDuration(s string) bool { _, err := time.ParseDuration(s); return err == nil } Try / catch
if err := cmd.parseDurations(); err != nil {
if strings.Contains(err.Error(), "stdout_repeat_duration") {
return fmt.Errorf("fix stdout_repeat_duration in mock driver config: %w", err)
}
return err
} Prevention
- Use explicit units: "500ms", "1s", "0" to disable.
- Trim whitespace from config values sourced from templates or env.
- Validate all three repeat durations together in pre-submit checks.
When it happens
Trigger: Mock driver config sets stdout_repeat_duration to a malformed string (e.g. "100msx", "", "every 5s", "0.5") — RecoverTask or StartTask config parsing fails immediately.
Common situations: Copy-paste typos in job specs; forgetting the unit ("500" instead of "500ms"); interpolated env vars empty; locale-formatted numbers with commas.
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
- run_for %v not a valid duration: %v
- stderr_repeat_duration %v not a valid duration: %v
- failed to parse raft_logstore verification interval %q: %w
- failed to parse start_timeout: %v
- start_block_for %v not a valid duration: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/e37e4ef62344fe0d.
Report an issue: GitHub.