{"record":{"id":"b03567588be0742d","repo":"hashicorp/nomad","slug":"must-specify-at-least-one-namespace","errorCode":null,"errorMessage":"must specify at least one namespace","messagePattern":"must specify at least one namespace","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/namespace_endpoint.go","lineNumber":58,"sourceCode":"\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\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"namespace\", \"upsert_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 there is at least one namespace\n\tif len(args.Namespaces) == 0 {\n\t\treturn fmt.Errorf(\"must specify at least one namespace\")\n\t}\n\n\t// Validate the namespaces and set the hash\n\tfor _, ns := range args.Namespaces {\n\t\tif err := ns.Validate(); err != nil {\n\t\t\treturn fmt.Errorf(\"Invalid namespace %q: %v\", ns.Name, err)\n\t\t}\n\n\t\tns.SetHash()\n\t}\n\n\t// Update via Raft\n\t_, index, err := n.srv.raftApply(structs.NamespaceUpsertRequestType, args)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Update the index","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/namespace_endpoint.go#L40-L76","documentation":"The namespaces Upsert endpoint requires a non-empty batch. An UpsertNamespaces request with zero namespaces is rejected after management-ACL checks, before per-namespace validation, since there is nothing to write.","triggerScenarios":"Calling the Namespace.Upsert RPC or PUT /v1/namespaces with an empty Namespaces array (e.g. `nomad namespace` tooling, Terraform provider submitting an empty plan, or a script posting `{\"Namespaces\":[]}`).","commonSituations":"Infrastructure-as-code plans that evaluate to zero namespace resources and still issue an empty PUT; a JSON template with an empty list; a loop that filters out all namespaces before the request.","solutions":["Ensure args.Namespaces contains at least one Namespace object before calling the RPC.","Skip the API call entirely when the batch is empty on the client side.","Check the upstream generation logic (Terraform plan, script loop) for why the list is empty."],"exampleFix":"// before\nclient.Namespaces().Upsert(&structs.NamespaceUpsertRequest{Namespaces: []*structs.Namespace{}}, nil)\n// after\nif len(namespaces) == 0 { return nil }\nclient.Namespaces().Upsert(&structs.NamespaceUpsertRequest{Namespaces: namespaces}, nil)","handlingStrategy":"validation","validationCode":"if len(namespaces) == 0 {\n    return nil // nothing to upsert; skip the API call\n}","typeGuard":"func hasNamespaces(req *structs.NamespaceUpsertRequest) bool {\n    return req != nil && len(req.Namespaces) > 0\n}","tryCatchPattern":"_, err := client.Namespaces().Upsert(req, nil)\nif err != nil && strings.Contains(err.Error(), \"must specify at least one namespace\") {\n    log.Printf(\"empty namespace batch; check upstream plan generation\")\n}\nreturn err","preventionTips":["No-op early when an IaC plan yields zero namespaces.","Never send placeholder empty arrays; omit the call.","Diff generated namespace lists before submission to catch filters dropping everything."],"tags":["nomad","namespace","validation","empty-input"],"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"}