hashicorp/nomad · error
KillTimout (%s) longer than the group's ProgressDeadline (%s
Error message
KillTimout (%s) longer than the group's ProgressDeadline (%s)
What it means
Raised during Task validation in nomad/structs/structs.go:8262 when a service job task's kill_timeout exceeds the task group's update block ProgressDeadline (and ProgressDeadline > 0). During a deployment, if a task fails health checks Nomad waits until the progress deadline before proceeding; a kill_timeout longer than that deadline makes the kill-then-restart sequence incoherent, so Nomad rejects it.
Source
Thrown at nomad/structs/structs.go:8262
mErr.Errors = append(mErr.Errors, errors.New("Task name cannot include null characters"))
}
if t.Driver == "" {
mErr.Errors = append(mErr.Errors, errors.New("Missing task driver"))
}
if t.KillTimeout < 0 {
mErr.Errors = append(mErr.Errors, errors.New("KillTimeout must be a positive value"))
} else {
// Validate the group's update strategy does not conflict with the
// task's kill_timeout for service jobs.
//
// progress_deadline = 0 has a special meaning so it should not be
// validated against the task's kill_timeout.
conflictsWithProgressDeadline := jobType == JobTypeService &&
tg.Update != nil &&
tg.Update.ProgressDeadline > 0 &&
t.KillTimeout > tg.Update.ProgressDeadline
if conflictsWithProgressDeadline {
mErr.Errors = append(mErr.Errors, fmt.Errorf("KillTimout (%s) longer than the group's ProgressDeadline (%s)",
t.KillTimeout, tg.Update.ProgressDeadline))
}
}
if t.ShutdownDelay < 0 {
mErr.Errors = append(mErr.Errors, errors.New("ShutdownDelay must be a positive value"))
}
// Validate the resources.
if t.Resources == nil {
mErr.Errors = append(mErr.Errors, errors.New("Missing task resources"))
} else if err := t.Resources.Validate(); err != nil {
mErr.Errors = append(mErr.Errors, err)
}
// Validate the log config
if t.LogConfig == nil {
mErr.Errors = append(mErr.Errors, errors.New("Missing Log Config"))
} else if err := t.LogConfig.Validate(tg.EphemeralDisk); err != nil {View on GitHub (pinned to 482b49bf1a)
Solutions
- Lower kill_timeout so it is <= update.progress_deadline.
- Raise update { progress_deadline } to be strictly greater than kill_timeout.
- Remove the custom kill_timeout to use the 5s default if graceful shutdown is not required.
Example fix
// before
update { progress_deadline = "5m" }
task "web" { kill_timeout = "10m" }
// after
update { progress_deadline = "15m" }
task "web" { kill_timeout = "10m" } Defensive patterns
Strategy: validation
Validate before calling
if job.Type == "service" && tg.Update != nil && tg.Update.ProgressDeadline > 0 {
for _, t := range tg.Tasks {
if t.KillTimeout > tg.Update.ProgressDeadline {
return fmt.Errorf("task %s: kill_timeout %s exceeds progress_deadline %s", t.Name, t.KillTimeout, tg.Update.ProgressDeadline)
}
}
} Prevention
- Always set progress_deadline > the largest kill_timeout in the group.
- Review both values together when tuning graceful shutdown.
- Use nomad job validate in CI to catch cross-field conflicts.
When it happens
Trigger: Service job with update { progress_deadline = 5m } and a task kill_timeout = 10m; calling tg.Validate/job Validate with t.KillTimeout > tg.Update.ProgressDeadline for JobTypeService.
Common situations: Users raise kill_timeout so graceful shutdown can finish but forget to extend progress_deadline; defaults changed in one place (kill_timeout = 30m) interacting with a small progress_deadline; deployments stuck then failing validation after a job edit.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- missing deployment ID
- must specify at least one healthy/unhealthy allocation ID
- MaxParallel must be >= 0 but found %d
- Missing HealthCheck
- missing secret ID
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/267b29a9fc233a9e.
Report an issue: GitHub.