hashicorp/nomad · error
stderr_repeat_duration %v not a valid duration: %v
Error message
stderr_repeat_duration %v not a valid duration: %v
What it means
The last duration parse in parseDurations converts StderrRepeatDur into stderrRepeatDuration. Invalid input yields 'stderr_repeat_duration %v not a valid duration: %v', aborting RecoverTask or parseDriverConfig for the mock driver. Behavior and fixes mirror the run_for and stdout cases.
Source
Thrown at drivers/mock/driver.go:420
}
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)
}
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)View on GitHub (pinned to 482b49bf1a)
Solutions
- Set stderr_repeat_duration to a valid duration string like "250ms", "2s", "5m".
- Trim whitespace and remove stray characters; rely on the wrapped ParseDuration message to spot the bad token.
- Ensure interpolated variables resolve to well-formed durations.
- If recovery is failing on old state, stop/resubmit the task with corrected config.
Example fix
// before stderr_repeat_duration = "2 hours " // after stderr_repeat_duration = "2h"
Defensive patterns
Strategy: validation
Validate before calling
if _, err := time.ParseDuration(c.StderrRepeatDur); err != nil {
return fmt.Errorf("stderr_repeat_duration must be like 250ms, got %q", c.StderrRepeatDur)
} 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(), "stderr_repeat_duration") {
return fmt.Errorf("fix stderr_repeat_duration in mock driver config: %w", err)
}
return err
} Prevention
- Use valid Go duration strings ("2s", "250ms") with no trailing spaces or words.
- Add a schema/CI check on mock driver duration fields before job submission.
- When recovery fails on old state, resubmit the job with corrected durations instead of retrying recovery.
When it happens
Trigger: Mock driver config sets stderr_repeat_duration to an unparseable string ("2hours ", "soon", "", "NaN"); error raised during RecoverTask or StartTask config parsing.
Common situations: Trailing whitespace or wrong unit suffix in job files; templated values from env/consul-template empty at submit time; confusion between mock's parseDuration extension and plain time.ParseDuration semantics.
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
- stdout_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/46cb0628692bd34c.
Report an issue: GitHub.