hashicorp/nomad · error · ErrMultipleNamespaces
%w, Namespaces: %s
Error message
%w, Namespaces: %s
What it means
Nomad jobs may specify only one Vault cluster/namespace per job. This error is returned by the job Vault admission hook when the job declares Vault blocks spanning more than one namespace, listing the offending namespaces after the wrapped ErrMultipleNamespaces sentinel (check errors with errors.Is).
Source
Thrown at nomad/job_endpoint_hook_vault_ce.go:21
//go:build !ent
package nomad
import (
"errors"
"fmt"
"strings"
"github.com/hashicorp/nomad/nomad/structs"
)
// validateNamespaces returns an error if the job contains any Vault namespaces.
func (jobVaultHook) validateNamespaces(blocks map[string]map[string]*structs.Vault) error {
requestedNamespaces := structs.VaultNamespaceSet(blocks)
if len(requestedNamespaces) > 0 {
return fmt.Errorf("%w, Namespaces: %s", ErrMultipleNamespaces, strings.Join(requestedNamespaces, ", "))
}
return nil
}
func (h jobVaultHook) validateClustersForNamespace(_ *structs.Job, blocks map[string]map[string]*structs.Vault) error {
for _, tg := range blocks {
for _, vault := range tg {
if vault.Cluster != "default" {
return errors.New("non-default Vault cluster requires Nomad Enterprise")
}
}
}
return nil
}
func (h jobVaultHook) Mutate(job *structs.Job) (*structs.Job, []error, error) {
for _, tg := range job.TaskGroups {View on GitHub (pinned to 482b49bf1a)
Solutions
- Set the same vault.namespace in every vault block across all task groups (or omit namespace to use the agent default)
- Move jobs needing different namespaces into separate job submissions
- Remove the vault namespace field entirely and rely on the Nomad agent's default Vault namespace
Example fix
// before
group "app" { vault { namespace = "team-a" } }
group "admin" { vault { namespace = "team-b" } }
// after
group "app" { vault { namespace = "team-a" } }
group "admin" { vault { namespace = "team-a" } } Defensive patterns
Strategy: validation
Validate before calling
nss := structs.VaultNamespaceSet(job.ToVaultBlocks())
if len(nss) > 1 {
return fmt.Errorf("job uses %d vault namespaces: %s", len(nss), strings.Join(nss, ", "))
} Type guard
func singleVaultNamespace(blocks map[string]map[string]*structs.Vault) bool {
return len(structs.VaultNamespaceSet(blocks)) <= 1
} Prevention
- Standardize one vault namespace per job in your templates
- Lint job specs for multiple distinct vault.namespace values before submit
- Get the namespace from a single variable rather than per-group literals
When it happens
Trigger: Submitting (POST /v1/jobs or nomad job run) a job whose vault blocks, summed across all task groups via structs.VaultNamespaceSet, resolve to more than one distinct Vault namespace.
Common situations: Copy-pasting task group definitions from jobs that each used a different Vault namespace; teams migrating namespaces leaving one group pointing at the old one; templated job files with per-group vault namespace variables.
Related errors
- Vault validation failed: %v
- Disconnect cannot be configured with both lost_after and sto
- lost_after cannot be a negative duration
- stop_after cannot be a negative duration
- Missing job ID
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/90e9cd663797fec2.
Report an issue: GitHub.