hashicorp/nomad · error
plan_rejection_tracker.node_window must be greater than 0
Error message
plan_rejection_tracker.node_window must be greater than 0
What it means
convertServerConfig in command/agent/agent.go validates the server's plan_rejection_tracker config block. When the tracker is configured, node_window must be a positive integer because it is the time window (likely in duration/string form used by the tracker) over which plan rejections are counted against node_threshold. A zero value would make the rejection tracker meaningless (division-by-window / no window to accumulate rejections), so the agent refuses to start or reload rather than run with a nonsensical tracker.
Source
Thrown at command/agent/agent.go:631
// Set deployment rate limit
if rate := agentConfig.Server.DeploymentQueryRateLimit; rate == 0 {
conf.DeploymentQueryRateLimit = deploymentwatcher.LimitStateQueriesPerSecond
} else if rate > 0 {
conf.DeploymentQueryRateLimit = rate
} else {
return nil, fmt.Errorf("deploy_query_rate_limit must be greater than 0")
}
// Set plan rejection tracker configuration.
if planRejectConf := agentConfig.Server.PlanRejectionTracker; planRejectConf != nil {
if planRejectConf.Enabled != nil {
conf.NodePlanRejectionEnabled = *planRejectConf.Enabled
}
conf.NodePlanRejectionThreshold = planRejectConf.NodeThreshold
if planRejectConf.NodeWindow == 0 {
return nil, fmt.Errorf("plan_rejection_tracker.node_window must be greater than 0")
} else {
conf.NodePlanRejectionWindow = planRejectConf.NodeWindow
}
}
conf.PlanApplyPipeline = agentConfig.Server.PlanApplyPipeline
// Add Enterprise license configs
conf.LicenseConfig = &nomad.LicenseConfig{
BuildDate: agentConfig.Version.BuildDate,
AdditionalPubKeys: agentConfig.Server.licenseAdditionalPublicKeys,
LicenseEnvBytes: agentConfig.Server.LicenseEnv,
LicensePath: agentConfig.Server.LicensePath,
NonProduction: agentConfig.Server.NonProduction,
}
// Add the search configuration
if search := agentConfig.Server.Search; search != nil {
conf.SearchConfig = &structs.SearchConfig{View on GitHub (pinned to 482b49bf1a)
Solutions
- Set plan_rejection_tracker.node_window to a positive value (e.g. node_window = "10m") in the server block.
- If the tracker was not intentionally enabled, remove the plan_rejection_tracker block (or its enabled = true) entirely.
- Check templated/HCL-rendered config for an empty or 0 value being substituted for node_window.
- After fixing, restart the agent or run `nomad agent reload` / SIGHUP.
Example fix
// before (server.hcl)
server {
plan_rejection_tracker {
enabled = true
node_threshold = 100
node_window = 0
}
}
// after
server {
plan_rejection_tracker {
enabled = true
node_threshold = 100
node_window = "10m"
}
} Defensive patterns
Strategy: validation
Validate before calling
// before deploying, validate the rendered HCL
// nomad validate server.hcl
// programmatic check on the parsed config:
if cfg.Server.PlanRejectionTracker != nil && cfg.Server.PlanRejectionTracker.NodeWindow == 0 {
return fmt.Errorf("plan_rejection_tracker.node_window must be set to a positive value")
} Prevention
- Always set enabled, node_threshold, and node_window together when configuring the tracker.
- Run `nomad validate` in CI on every rendered config artifact.
- Prefer removing the block entirely over partially commenting fields.
When it happens
Trigger: Running `nomad agent -server` or `nomad agent reload` where the server config contains a plan_rejection_tracker block (enabled or with node_threshold set) but omits node_window, or sets node_window = 0. Also triggered on SIGHUP reload via handleReload since the same conversion runs.
Common situations: Copy-pasting a partial plan_rejection_tracker example that sets only enabled/threshold; operators enabling the tracker to mitigate plan-queue flooding and forgetting the window; config templating that injects an empty window value; upgrade paths where a previously optional field became required.
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
- failed to parse start_timeout: %v
- failed to parse config:
- only one of cgroups_v1_override and cgroups_v2_override may
- work_dir must be an absolute path
- require only one of PemKey or PemKeyFile
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f073070e822e8b07.
Report an issue: GitHub.