{"record":{"id":"67761403254fa0c2","repo":"hashicorp/nomad","slug":"scheduler-resulted-in-an-unexpected-number-of-plan","errorCode":null,"errorMessage":"scheduler resulted in an unexpected number of plans: %v","messagePattern":"scheduler resulted in an unexpected number of plans: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/job_endpoint.go","lineNumber":1908,"sourceCode":"\t// Create an in-memory Planner that returns no errors and stores the\n\t// submitted plan and created evals.\n\tplanner := &sstructs.PlanBuilder{\n\t\tState: &snap.StateStore,\n\t}\n\n\t// Create the scheduler and run it\n\tsched, err := scheduler.NewScheduler(eval.Type, j.logger, j.srv.workersEventCh, snap, planner)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err := sched.Process(eval); err != nil {\n\t\treturn err\n\t}\n\n\t// Annotate and store the diff\n\tif plans := len(planner.Plans); plans != 1 {\n\t\treturn fmt.Errorf(\"scheduler resulted in an unexpected number of plans: %v\", plans)\n\t}\n\tannotations := planner.Plans[0].Annotations\n\tif args.Diff {\n\t\tjobDiff, err := existingJob.Diff(args.Job, true)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to create job diff: %v\", err)\n\t\t}\n\n\t\tif err := scheduler.Annotate(jobDiff, annotations); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to annotate job diff: %v\", err)\n\t\t}\n\t\treply.Diff = jobDiff\n\t}\n\n\t// Grab the failures\n\tif len(planner.Evals) != 1 {\n\t\treturn fmt.Errorf(\"scheduler resulted in an unexpected number of eval updates: %v\", planner.Evals)\n\t}","sourceCodeStart":1890,"sourceCodeEnd":1926,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/job_endpoint.go#L1890-L1926","documentation":"Job.Plan ran the scheduler worker for the evaluation, expecting exactly one scheduling plan back, but got a different count. A count of 0 usually means the scheduler produced no plan for the proposed job; >1 indicates an internal scheduler invariant violation. The endpoint aborts annotation and returns the count.","triggerScenarios":"Job.Plan where after sched.Process(eval), len(planner.Plans) != 1 at nomad/job_endpoint.go:1908 — commonly 0 plans when the planner's SubmitPlan never fired for the fake eval created from args.Job.","commonSituations":"Planning a job whose constraints/placeability produce no eval work in that scheduler (e.g. system-job edge cases); scheduler worker errors swallowed upstream; Nomad bugs after version upgrades changing plan submission behavior; job type mapping to an unexpected scheduler.","solutions":["Inspect server logs around the plan request for scheduler errors explaining why no plan was produced.","Retry the plan request; transient worker issues can yield zero plans.","Validate the job type and placement constraints ('nomad job validate') to ensure a scheduler can process it.","If reproducible (especially plans > 1), capture a nomad operator debug bundle and file a bug — this path should be invariant."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Ensure the job type is schedulable before planning\nif *job.Type == \"system\" || *job.Type == \"batch\" {\n    // verify constraints/placeability with validate first\n    if _, _, err := client.Jobs().Validate(job, nil); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":"plan, _, err := client.Jobs().Plan(job, true, nil)\nif err != nil && strings.Contains(err.Error(), \"unexpected number of plans\") {\n    // one retry after brief backoff; persistent counts (>1) indicate a Nomad bug — capture a debug bundle\n}","preventionTips":["Retry plan requests once on transient scheduler failures.","Keep agents/servers on matching Nomad versions to avoid plan-submission drift.","Watch server logs for scheduler worker errors during plan testing."],"tags":["nomad","scheduler","plan"],"backgroundTag":"scheduler-plan-count-mismatch","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"}