{"record":{"id":"d6a63b345a6a523c","repo":"hashicorp/nomad","slug":"evals-must-be-deleted-by-either-id-or-filter","errorCode":null,"errorMessage":"evals must be deleted by either ID or filter","messagePattern":"evals must be deleted by either ID or filter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/eval_endpoint.go","lineNumber":478,"sourceCode":"\t// This RPC endpoint is very destructive and alters Nomad's core state,\n\t// meaning only those with management tokens can call it.\n\tif aclObj, err := e.srv.ResolveACL(args); err != nil {\n\t\treturn err\n\t} else if !aclObj.IsManagement() {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\tif args.Filter != \"\" && !e.srv.peersCache.ServersMeetMinimumVersion(\n\t\te.srv.Region(), minVersionEvalDeleteByFilter, true) {\n\t\treturn fmt.Errorf(\n\t\t\t\"all servers must be running version %v or later to delete evals by filter\",\n\t\t\tminVersionEvalDeleteByFilter)\n\t}\n\tif args.Filter != \"\" && len(args.EvalIDs) > 0 {\n\t\treturn fmt.Errorf(\"evals cannot be deleted by both ID and filter\")\n\t}\n\tif args.Filter == \"\" && len(args.EvalIDs) == 0 {\n\t\treturn fmt.Errorf(\"evals must be deleted by either ID or filter\")\n\t}\n\n\t// The eval broker must be disabled otherwise Nomad's state will likely get\n\t// wild in a very un-fun way.\n\tif e.srv.evalBroker.Enabled() {\n\t\treturn errors.New(\"eval broker is enabled; eval broker must be paused to delete evals\")\n\t}\n\n\tif args.Filter != \"\" {\n\t\tcount, index, err := e.deleteEvalsByFilter(args)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// Update the index and return.\n\t\treply.Index = index\n\t\treply.Count = count\n\t\treturn nil","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/eval_endpoint.go#L460-L496","documentation":"Guard in Eval.Delete: the request provided neither a list of eval IDs nor a filter expression, so the destructive delete has nothing to act on; exactly one selector must be present.","triggerScenarios":"Sending an EvalDeleteRequest where args.Filter == \"\" and len(args.EvalIDs) == 0.","commonSituations":"Empty ID list from upstream code that filtered evals client-side and found none; building the request programmatically without checking that at least one selection criterion is present.","solutions":["Populate EvalIDs with at least one eval ID or set Filter to a valid expression","Check that the eval selection is non-empty before issuing the RPC"],"exampleFix":"// before\nreq := &structs.EvalDeleteRequest{}\n// after\nif len(ids) > 0 {\n    req := &structs.EvalDeleteRequest{EvalIDs: ids}\n}","handlingStrategy":"validation","validationCode":"if filter == \"\" && len(ids) == 0 { return errors.New(\"eval delete requires IDs or a filter\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check the selection is non-empty before sending the request","Avoid client-side pre-filtering that can yield empty ID lists silently","Log a warning when a delete request is skipped for lack of criteria"],"tags":["nomad","rpc","validation","empty-request"],"backgroundTag":"missing-required-argument","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"}