hashicorp/nomad · error
can not delete default namespace
Error message
can not delete default namespace
What it means
DeleteNamespaces refuses to delete the built-in 'default' namespace (structs.DefaultNamespace). The default namespace is a system sentinel that jobs, ACLs, and API defaults rely on, so deleting it would break cluster invariants. The check runs before any state mutation.
Source
Thrown at nomad/namespace_endpoint.go:112
if authErr != nil {
return structs.ErrPermissionDenied
}
defer metrics.MeasureSince([]string{"nomad", "namespace", "delete_namespaces"}, time.Now())
// Check management permissions
if aclObj, err := n.srv.ResolveACL(args); err != nil {
return err
} else if !aclObj.IsManagement() {
return structs.ErrPermissionDenied
}
// Validate at least one namespace
if len(args.Namespaces) == 0 {
return fmt.Errorf("must specify at least one namespace to delete")
}
if slices.Contains(args.Namespaces, structs.DefaultNamespace) {
return fmt.Errorf("can not delete default namespace")
}
// snapshot the state once, because we'll be doing many checks and want
// consistend state
snap, err := n.srv.fsm.State().Snapshot()
if err != nil {
return err
}
var mErr multierror.Error
for _, ns := range args.Namespaces {
// make sure this namespace exists before we start making costly checks
exists, _ := snap.NamespaceByName(nil, ns)
if exists == nil {
continue
}
// do a check across jobs, allocations, volumes and variables to make sure we'reView on GitHub (pinned to 482b49bf1a)
Solutions
- Remove "default" from the Namespaces list before calling Delete.
- Filter with slices.DeleteFunc(names, func(n string) bool { return n == "default" }).
- Migrate workloads to another namespace instead of trying to delete default.
Example fix
// before
client.Namespaces().Delete(&api.NamespaceDeleteRequest{Namespaces: allNames})
// after
names := slices.DeleteFunc(allNames, func(n string) bool { return n == structs.DefaultNamespace })
client.Namespaces().Delete(&api.NamespaceDeleteRequest{Namespaces: names}) Defensive patterns
Strategy: validation
Validate before calling
names := slices.DeleteFunc(names, func(n string) bool { return n == "default" })
if len(names) == 0 { return nil }
_, err := client.Namespaces().Delete(&api.NamespaceDeleteRequest{Namespaces: names}) Type guard
func deletableNamespaces(names []string) []string {
out := make([]string, 0, len(names))
for _, n := range names { if n != "default" { out = append(out, n) } }
return out
} Prevention
- Never include built-in namespaces in bulk deletes.
- Filter wildcard listings before deleting.
- Centralize namespace cleanup in one helper that excludes reserved names.
When it happens
Trigger: Including "default" in the Namespaces slice of a NamespaceDeleteRequest, e.g. deleting all namespaces from a wildcard listing without filtering out 'default'.
Common situations: Bulk cleanup scripts that enumerate and delete all namespaces; operators trying to 'reset' a cluster; tests reusing a wildcard delete helper.
Related errors
- must specify at least one namespace to delete
- namespace %q has non-terminal jobs in regions: %v
- error parsing: root should be an object
- missing policy name
- cannot specify Accessor ID
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/0a4dddc0e4d1e95b.
Report an issue: GitHub.