{"record":{"id":"449f701b4abe9e57","repo":"hashicorp/nomad","slug":"feature-node-pools-governance-is-unlicensed","errorCode":null,"errorMessage":"Feature \"Node Pools Governance\" is unlicensed","messagePattern":"Feature \"Node Pools Governance\" is unlicensed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/node_pool_endpoint_ce.go","lineNumber":16,"sourceCode":"// Copyright IBM Corp. 2015, 2026\n// SPDX-License-Identifier: BUSL-1.1\n\n//go:build !ent\n\npackage nomad\n\nimport (\n\t\"errors\"\n\n\t\"github.com/hashicorp/nomad/nomad/structs\"\n)\n\nfunc (n *NodePool) validateLicense(pool *structs.NodePool) error {\n\tif pool != nil && pool.SchedulerConfiguration != nil {\n\t\treturn errors.New(`Feature \"Node Pools Governance\" is unlicensed`)\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/node_pool_endpoint_ce.go#L1-L21","documentation":"Nomad's Node Pools Governance feature (attaching a SchedulerConfiguration to a NodePool) is Enterprise-only. validateLicense rejects any NodePool whose SchedulerConfiguration is non-nil when the feature is unlicensed, so the RPC (List, GetNodePool, UpsertNodePools, DeleteNodePools) fails. This is an intentional license gate, not a bug.","triggerScenarios":"Calling NodePool List/GetNodePool/UpsertNodePools/DeleteNodePools against a Nomad CE (or unlicensed Ent) cluster while the NodePool object carries a SchedulerConfiguration field (typically a policy override target).","commonSituations":"Infrastructure-as-code written for Nomad Enterprise applied to a Community Edition cluster; upgrading tooling that newly sets scheduler_configuration; testing enterprise features locally without a license.","solutions":["Remove the scheduler_configuration block from your node_pool definitions","Upgrade to Nomad Enterprise with a license covering Node Pools Governance","Stop relying on SchedulerConfiguration on node pools; configure scheduler settings globally via the /v1/operator/scheduler/configuration endpoint instead"],"exampleFix":"// before (HCL)\nnode_pool \"prod\" {\n  scheduler_configuration {\n    scheduler_algorithm = \"spread\"\n  }\n}\n// after\nnode_pool \"prod\" {\n  description = \"production pool\"\n}","handlingStrategy":"validation","validationCode":"// Remove enterprise-only fields before calling the API\nif pool.SchedulerConfiguration != nil {\n    pool.SchedulerConfiguration = nil\n}\nclient.NodePools().Upsert(pool, nil)","typeGuard":"func isGovernanceCapable(p *api.NodePool) bool {\n    return p != nil && p.SchedulerConfiguration == nil\n}","tryCatchPattern":null,"preventionTips":["Keep CE and Ent node pool HCL templates separate","Filter node pool payloads to CE-supported fields","Test IaC against a CE cluster if that is the deployment target"],"tags":["nomad","licensing","enterprise","node-pools"],"backgroundTag":"feature-unlicensed","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"}