{"record":{"id":"5ba0af407a54fb08","repo":"hashicorp/nomad","slug":"node-pool-q-has-nodes-in-regions-v","errorCode":null,"errorMessage":"node pool %q has nodes in regions: %v","messagePattern":"node pool %q has nodes in regions: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/node_pool_endpoint.go","lineNumber":284,"sourceCode":"\t}\n\tif slices.Contains(args.Names, \"\") {\n\t\treturn structs.NewErrRPCCodedf(http.StatusBadRequest, \"node pool name is empty\")\n\t}\n\n\t// Verify that the node pools we're deleting do not have nodes or\n\t// non-terminal jobs in this region or in any federated region.\n\tvar mErr multierror.Error\n\tfor _, name := range args.Names {\n\t\tregionsWithNonTerminal, regionsWithNodes, err := n.nodePoolRegionsInUse(args.AuthToken, name)\n\t\tif err != nil {\n\t\t\t_ = multierror.Append(&mErr, err)\n\t\t}\n\t\tif len(regionsWithNonTerminal) != 0 {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\n\t\t\t\t\"node pool %q has non-terminal jobs in regions: %v\", name, regionsWithNonTerminal))\n\t\t}\n\t\tif len(regionsWithNodes) != 0 {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\n\t\t\t\t\"node pool %q has nodes in regions: %v\", name, regionsWithNodes))\n\t\t}\n\t}\n\n\tif err := mErr.ErrorOrNil(); err != nil {\n\t\treturn err\n\t}\n\n\t// Delete via Raft.\n\t_, index, err := n.srv.raftApply(structs.NodePoolDeleteRequestType, args)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treply.Index = index\n\treturn nil\n}\n","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/node_pool_endpoint.go#L266-L302","documentation":"DeleteNodePools also blocks deletion while the node pool still contains nodes. nodePoolRegionsInUse detects nodes assigned to the pool and the endpoint returns this error naming the regions where those nodes live, as part of a multierror.","triggerScenarios":"Deleting a node pool that has registered (non-archived) nodes in any region — e.g. `nomad node pool delete gpu` while agents still report in from that pool.","commonSituations":"Decommissioning a pool of clients without draining/deregistering them first; stale node registrations from hosts that were wiped but whose agents are still registered.","solutions":["Drain and stop the Nomad agents on the nodes (`nomad node drain <id>`, then stop the agent) so they deregister","Force-deregister stale nodes: `nomad node status` then `nomad node eligibility -disable`/agent shutdown, or purge via the API","Re-attempt the pool deletion once `nomad node status -filter 'NodePool==\"<pool>\"'` returns no nodes","Use force-delete only after confirming nodes are truly gone"],"exampleFix":"// before\n$ nomad node pool delete gpu\nError: node pool \"gpu\" has nodes in regions: [us-west]\n// after\n$ nomad node drain -disable -detach <node-id> && systemctl stop nomad\n$ nomad node pool delete gpu","handlingStrategy":"validation","validationCode":"nodes, _ := client.Nodes().List(nil)\nfor _, n := range nodes {\n    if n.NodePool == poolName {\n        return fmt.Errorf(\"node %s still in pool %s\", n.ID, poolName)\n    }\n}","typeGuard":null,"tryCatchPattern":"err := client.NodePools().Delete([]string{poolName}, wr)\nif err != nil && strings.Contains(err.Error(), \"has nodes in regions\") {\n    // drain/deregister nodes, then retry\n}","preventionTips":["Drain and deregister nodes before pool deletion","Query `nomad node status` filtered by pool pre-deletion","Purge stale registrations from decommissioned hosts","Verify node pool empty across all regions before delete"],"tags":["nomad","node-pools","nodes","multi-region"],"backgroundTag":"resource-in-use","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"}