hashicorp/nomad · error
Error switching to ns %v: %v
Error message
Error switching to ns %v: %v
What it means
This error is returned by netNS.Set() when the setns(2) syscall (via unix.Setns with CLONE_NEWNET) fails to move the calling thread into the network namespace referenced by this open NetNS handle. It wraps the underlying OS error together with the namespace file name, so it indicates the file descriptor was valid but the kernel refused the namespace switch.
Source
Thrown at client/lib/nsutil/ns_linux.go:67
if err := ns.errorIfClosed(); err != nil {
return err
}
if err := ns.file.Close(); err != nil {
return fmt.Errorf("Failed to close %q: %v", ns.file.Name(), err)
}
ns.closed = true
return nil
}
func (ns *netNS) Set() error {
if err := ns.errorIfClosed(); err != nil {
return err
}
if err := unix.Setns(int(ns.Fd()), unix.CLONE_NEWNET); err != nil {
return fmt.Errorf("Error switching to ns %v: %v", ns.file.Name(), err)
}
return nil
}
type NetNS interface {
// Executes the passed closure in this object's network namespace,
// attempting to restore the original namespace before returning.
// However, since each OS thread can have a different network namespace,
// and Go's thread scheduling is highly variable, callers cannot
// guarantee any specific namespace is set unless operations that
// require that namespace are wrapped with Do(). Also, no code called
// from Do() should call runtime.UnlockOSThread(), or the risk
// of executing code in an incorrect namespace will be greater. See
// https://github.com/golang/go/wiki/LockOSThread for further details.
Do(toRun func(NetNS) error) error
// Sets the current network namespace to this object's network namespace.View on GitHub (pinned to 482b49bf1a)
Solutions
- Ensure the process has CAP_SYS_ADMIN (run as root or add the capability) since setns(CLONE_NEWNET) requires it
- Verify the target namespace still exists (the owning container/task has not exited) and re-open it via GetNS if needed
- Check seccomp/AppArmor/container runtime profiles allow setns
- Do not call Set() on a NetNS after Close(); keep the handle open for the duration of the switch
- Inspect the wrapped %v kernel error (EPERM vs EINVAL vs EBADF) to pinpoint the cause
Example fix
// before
if err := ns.Set(); err != nil {
return err // fails with EPERM in unprivileged container
}
// after
if !hasCapSysAdmin() {
return fmt.Errorf("setns requires CAP_SYS_ADMIN; run privileged")
}
if err := ns.Set(); err != nil {
return fmt.Errorf("switch to netns failed: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
func canSetns() error {
if _, err := os.Stat("/proc/self/ns/net"); err != nil {
return fmt.Errorf("procfs unavailable: %w", err)
}
if !hasCapSysAdmin() {
return fmt.Errorf("CAP_SYS_ADMIN required for setns")
}
return nil
} Type guard
func nsUsable(ns NetNS) bool {
n, ok := ns.(*netNS)
return ok && n.file != nil && !n.closed
} Try / catch
if err := ns.Set(); err != nil {
var perr syscall.Errno
if errors.As(err, &perr) && perr == syscall.EPERM {
return fmt.Errorf("insufficient privileges to switch netns: %w", err)
}
return fmt.Errorf("netns switch failed: %w", err)
} Prevention
- Run components that switch namespaces with CAP_SYS_ADMIN
- Never use a NetNS handle after Close(); track its lifetime
- Confirm the owning container/task is alive before using its netns
- Log the wrapped kernel errno to distinguish EPERM/EINVAL/EBADF
When it happens
Trigger: Calling Set() (directly or via Do()) on a NetNS whose fd is no longer valid for setns — e.g. the namespace was destroyed, the process lacks CAP_SYS_ADMIN, or the fd was closed concurrently (which makes unix.Fd() reuse invalid).
Common situations: Running the client without root/CAP_SYS_ADMIN in a container missing SYS_ADMIN; a task's network namespace (e.g. a docker bridge ns) was torn down while the handle was still in use; seccomp/AppArmor policies blocking setns; using the handle after garbage collection closed the underlying file.
Related errors
- error switching to ns %v: %v
- Unable to find nobody user: %w
- Couldn't change owner/group of %v to (uid: %v, gid: %v): %w
- Failed to delete proc directory %q: %w
- error changing owner/group: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/1078589cf0ebc80e.
Report an issue: GitHub.