{"record":{"id":"f073070e822e8b07","repo":"hashicorp/nomad","slug":"plan-rejection-tracker-node-window-must-be-greater","errorCode":null,"errorMessage":"plan_rejection_tracker.node_window must be greater than 0","messagePattern":"plan_rejection_tracker\\.node_window must be greater than 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/agent.go","lineNumber":631,"sourceCode":"\n\t// Set deployment rate limit\n\tif rate := agentConfig.Server.DeploymentQueryRateLimit; rate == 0 {\n\t\tconf.DeploymentQueryRateLimit = deploymentwatcher.LimitStateQueriesPerSecond\n\t} else if rate > 0 {\n\t\tconf.DeploymentQueryRateLimit = rate\n\t} else {\n\t\treturn nil, fmt.Errorf(\"deploy_query_rate_limit must be greater than 0\")\n\t}\n\n\t// Set plan rejection tracker configuration.\n\tif planRejectConf := agentConfig.Server.PlanRejectionTracker; planRejectConf != nil {\n\t\tif planRejectConf.Enabled != nil {\n\t\t\tconf.NodePlanRejectionEnabled = *planRejectConf.Enabled\n\t\t}\n\t\tconf.NodePlanRejectionThreshold = planRejectConf.NodeThreshold\n\n\t\tif planRejectConf.NodeWindow == 0 {\n\t\t\treturn nil, fmt.Errorf(\"plan_rejection_tracker.node_window must be greater than 0\")\n\t\t} else {\n\t\t\tconf.NodePlanRejectionWindow = planRejectConf.NodeWindow\n\t\t}\n\t}\n\tconf.PlanApplyPipeline = agentConfig.Server.PlanApplyPipeline\n\n\t// Add Enterprise license configs\n\tconf.LicenseConfig = &nomad.LicenseConfig{\n\t\tBuildDate:         agentConfig.Version.BuildDate,\n\t\tAdditionalPubKeys: agentConfig.Server.licenseAdditionalPublicKeys,\n\t\tLicenseEnvBytes:   agentConfig.Server.LicenseEnv,\n\t\tLicensePath:       agentConfig.Server.LicensePath,\n\t\tNonProduction:     agentConfig.Server.NonProduction,\n\t}\n\n\t// Add the search configuration\n\tif search := agentConfig.Server.Search; search != nil {\n\t\tconf.SearchConfig = &structs.SearchConfig{","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/agent.go#L613-L649","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (server.hcl)\nserver {\n  plan_rejection_tracker {\n    enabled        = true\n    node_threshold = 100\n    node_window    = 0\n  }\n}\n// after\nserver {\n  plan_rejection_tracker {\n    enabled        = true\n    node_threshold = 100\n    node_window    = \"10m\"\n  }\n}","handlingStrategy":"validation","validationCode":"// before deploying, validate the rendered HCL\n// nomad validate server.hcl\n// programmatic check on the parsed config:\nif cfg.Server.PlanRejectionTracker != nil && cfg.Server.PlanRejectionTracker.NodeWindow == 0 {\n    return fmt.Errorf(\"plan_rejection_tracker.node_window must be set to a positive value\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["nomad","config-validation","server-config","plan-rejection-tracker"],"backgroundTag":"invalid-config-value","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}