hashicorp/nomad · error

start_block_for not a valid duration

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.

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.

Appendix: 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)