{"record":{"id":"39c09b244a3a57cb","repo":"hashicorp/nomad","slug":"multi-cluster-consul-is-unlicensed","errorCode":null,"errorMessage":"Multi-Cluster Consul is unlicensed.","messagePattern":"Multi-Cluster Consul is unlicensed\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs_ce.go","lineNumber":39,"sourceCode":"\t\treturn errors.New(\"Node Pools Governance is unlicensed.\")\n\t}\n\treturn nil\n}\n\nfunc (n *NamespaceVaultConfiguration) Canonicalize() {}\n\nfunc (n *NamespaceVaultConfiguration) Validate() error {\n\tif n != nil {\n\t\treturn errors.New(\"Multi-Cluster Vault is unlicensed.\")\n\t}\n\treturn nil\n}\n\nfunc (n *NamespaceConsulConfiguration) Canonicalize() {}\n\nfunc (n *NamespaceConsulConfiguration) Validate() error {\n\tif n != nil {\n\t\treturn errors.New(\"Multi-Cluster Consul is unlicensed.\")\n\t}\n\treturn nil\n}\n\nfunc (m *Multiregion) Validate(jobType string, jobDatacenters []string) error {\n\tif m != nil {\n\t\treturn errors.New(\"Multiregion jobs are unlicensed.\")\n\t}\n\n\treturn nil\n}\n\nfunc (p *ScalingPolicy) validateType() multierror.Error {\n\tvar mErr multierror.Error\n\n\t// Check policy type and target\n\tswitch p.Type {\n\tcase ScalingPolicyTypeHorizontal:","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs_ce.go#L21-L57","documentation":"NamespaceConsulConfiguration.Validate in the CE build returns \"Multi-Cluster Consul is unlicensed.\" for any non-nil per-namespace Consul configuration. Multi-Cluster Consul (per-namespace Consul cluster/namespace targeting) is enterprise-only, so the OSS stub rejects the block outright.","triggerScenarios":"Submitting a namespace whose NamespaceConsulConfiguration is non-nil (consul { cluster = \"...\" namespace = \"...\" } within a namespace spec) to a community-edition Nomad agent.","commonSituations":"Migrating namespace definitions from an Enterprise cluster to OSS; templates that emit the consul block unconditionally; attempting per-namespace Consul namespacing without an Enterprise license.","solutions":["Remove the per-namespace consul configuration block and rely on agent-level Consul configuration.","Upgrade to Nomad Enterprise with Multi-Cluster Consul entitlement and install a license.","Nil the NamespaceConsulConfiguration field in code that constructs namespace objects."],"exampleFix":"// before\nns.ConsulConfiguration = &structs.NamespaceConsulConfiguration{DefaultNamespace: \"default\"}\n// after\nns.ConsulConfiguration = nil // Multi-Cluster Consul requires Enterprise license","handlingStrategy":"validation","validationCode":"if ns.ConsulConfiguration != nil {\n\treturn errors.New(\"multi-cluster consul requires Nomad Enterprise\")\n}","typeGuard":"func consulLicensed(cfg *structs.NamespaceConsulConfiguration) bool { return cfg == nil }","tryCatchPattern":"if err := ns.Validate(); err != nil && strings.Contains(err.Error(), \"unlicensed\") {\n\tns.ConsulConfiguration = nil // retry without the block\n}","preventionTips":["Remove consul blocks from namespace templates targeting OSS","Detect cluster edition/entitlements before applying namespace specs","Use agent-level Consul configuration on community edition"],"tags":["nomad","licensing","enterprise","consul"],"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"}