hashicorp/nomad · error

run_for %v not a valid duration: %v

Error message

run_for %v not a valid duration: %v

What it means

The mock driver's Command config accepts human-friendly duration strings (e.g. "5s", "1m"). parseDurations converts RunFor via parseDuration, and any value time.ParseDuration cannot parse produces this wrapped error. It surfaces during task recovery (RecoverTask) or when parsing driver config in StartTask.

Source

Thrown at drivers/mock/driver.go:412

		taskConfig:      handle.Config,
		command:         taskState.Command,
		execCommand:     taskState.ExecCommand,
		procState:       drivers.TaskStateRunning,
		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
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix run_for in the task/driver config to a valid duration string like "30s", "5m", or "1h".
  2. Check the inner %v (from time.ParseDuration) for exactly which part failed to parse.
  3. If the value comes from interpolation, verify the variable is set and correctly formatted before submit.
  4. For recovered tasks with stale state, resubmit the job with corrected config instead of recovering.

Example fix

// before
c.RunFor = "10 minutes"
// after
c.RunFor = "10m"
Defensive patterns

Strategy: validation

Validate before calling

if _, err := time.ParseDuration(c.RunFor); err != nil {
    return fmt.Errorf("run_for must be a Go duration like 30s, got %q", c.RunFor)
}

Type guard

func validDuration(s string) bool { _, err := time.ParseDuration(s); return err == nil }

Try / catch

if err := cmd.parseDurations(); err != nil {
    // err names the field and bad value; fix config and resubmit
    return fmt.Errorf("invalid mock command config: %w", err)
}

Prevention

When it happens

Trigger: A mock task's command config sets run_for to something like "10", "forever", "5sec", or an empty string; parseDuration (which appends 's' for bare numbers per its own rules) still fails to parse it.

Common situations: Typo in job file ("run_for = "5 mintues""); passing a bare number with a unit the helper doesn't handle; config values interpolated from environment variables that came in empty or malformed; older persisted state with a now-invalid format.

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/1fb247ad36ff3b53. Report an issue: GitHub.