{"record":{"id":"b8f3ba0b8b5a0957","repo":"hashicorp/nomad","slug":"must-specify-at-least-one-namespace-to-delete","errorCode":null,"errorMessage":"must specify at least one namespace to delete","messagePattern":"must specify at least one namespace to delete","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/namespace_endpoint.go","lineNumber":108,"sourceCode":"\tif done, err := n.srv.forward(\"Namespace.DeleteNamespaces\", args, args, reply); done {\n\t\treturn err\n\t}\n\tn.srv.MeasureRPCRate(\"namespace\", structs.RateMetricWrite, args)\n\tif authErr != nil {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"namespace\", \"delete_namespaces\"}, time.Now())\n\n\t// Check management permissions\n\tif aclObj, err := n.srv.ResolveACL(args); err != nil {\n\t\treturn err\n\t} else if !aclObj.IsManagement() {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\t// Validate at least one namespace\n\tif len(args.Namespaces) == 0 {\n\t\treturn fmt.Errorf(\"must specify at least one namespace to delete\")\n\t}\n\n\tif slices.Contains(args.Namespaces, structs.DefaultNamespace) {\n\t\treturn fmt.Errorf(\"can not delete default namespace\")\n\t}\n\n\t// snapshot the state once, because we'll be doing many checks and want\n\t// consistend state\n\tsnap, err := n.srv.fsm.State().Snapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar mErr multierror.Error\n\tfor _, ns := range args.Namespaces {\n\t\t// make sure this namespace exists before we start making costly checks\n\t\texists, _ := snap.NamespaceByName(nil, ns)\n\t\tif exists == nil {","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/namespace_endpoint.go#L90-L126","documentation":"DeleteNamespaces is the RPC handler for deleting Nomad namespaces. Before mutating state it validates the request, and it rejects a request whose Namespaces list is empty because a bulk-delete RPC with no targets is meaningless and almost certainly a client bug. Nothing is deleted when this error is returned.","triggerScenarios":"Calling the Namespace.Delete RPC (or client.Namespaces().Delete) with an empty Namespaces slice in NamespaceDeleteRequest, e.g. building the request from a filtered list that ended up empty or omitting the field entirely.","commonSituations":"Automation scripts that filter a namespace list before deleting and end up with zero entries; CLI wrappers that pass no arguments; IaC tools producing empty diff sets.","solutions":["Pass at least one namespace name in the Namespaces field of the NamespaceDeleteRequest.","Check the input list length client-side and skip the RPC if it is empty.","If using the CLI, verify namespace names were parsed as arguments (quoting/flag mistakes can yield zero args)."],"exampleFix":"// before\nclient.Namespaces().Delete(&api.NamespaceDeleteRequest{})\n// after\nif len(names) == 0 { return nil }\nclient.Namespaces().Delete(&api.NamespaceDeleteRequest{Namespaces: names})","handlingStrategy":"validation","validationCode":"if len(req.Namespaces) == 0 {\n    return nil // nothing to delete; skip the RPC\n}\n_, err := client.Namespaces().Delete(&api.NamespaceDeleteRequest{Namespaces: req.Namespaces})","typeGuard":"func hasNamespaces(names []string) bool { return len(names) > 0 }","tryCatchPattern":null,"preventionTips":["Guard empty lists before bulk-delete RPCs.","Build delete requests from explicit name arguments, not implicit defaults.","Log the namespace list before sending for auditability."],"tags":["nomad","api-validation","namespace-delete"],"backgroundTag":"empty-request-validation","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"}