hashicorp/nomad · error
plugin_exit_after %v not a valid duration: %v
Error message
plugin_exit_after %v not a valid duration: %v
What it means
Same duration-parsing failure as start_block_for but for the PluginExitAfter config field: parseDriverConfig validates it during StartTask and rejects the whole task start if the string cannot be parsed as a Go duration.
Source
Thrown at drivers/mock/driver.go:438
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
}
func (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drivers.DriverNetwork, error) {
driverConfig, err := parseDriverConfig(cfg)
if err != nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Correct PluginExitAfter in the task driver config to a valid duration (e.g. "30s").
- Add an explicit unit suffix to any bare number.
- If the inner parse error points to a stray character, remove it and re-run the task.
Example fix
// before
cfg := map[string]interface{}{"PluginExitAfter": "120"}
// after
cfg := map[string]interface{}{"PluginExitAfter": "2m"} Defensive patterns
Strategy: validation
Validate before calling
if v, ok := cfg["PluginExitAfter"].(string); !ok || v == "" {
return errors.New("PluginExitAfter must be a non-empty duration string")
} else if _, err := time.ParseDuration(v); err != nil {
return fmt.Errorf("PluginExitAfter %q is not a valid duration: %v", v, err)
} Prevention
- Validate PluginExitAfter with time.ParseDuration before submitting the job.
- Avoid substituting bare numbers from environment variables; format them with an explicit unit.
When it happens
Trigger: Calling StartTask with a MockDriverConfig whose PluginExitAfter is not a valid Go duration string (e.g. "60" without a unit, or a non-numeric garbage value).
Common situations: Setting PluginExitAfter = "1m" vs "60" confusion; leaving the field as an empty string when a value was expected; environment-variable-substituted config yielding an unparseable 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
- start_block_for %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/fab0791dfc5b58ac.
Report an issue: GitHub.