hashicorp/nomad · info
Failed to close %q: %v
Error message
Failed to close %q: %v
What it means
netNS wraps an *os.File pointing at the namespace; Close closes that file handle. If the underlying file close fails, the library reports 'Failed to close <path>'. This is uncommon on Linux but indicates the descriptor could not be released cleanly.
Source
Thrown at client/lib/nsutil/ns_linux.go:54
runtime.LockOSThread()
defer runtime.UnlockOSThread()
return GetNS(getCurrentThreadNetNSPath())
}
func getCurrentThreadNetNSPath() string {
// /proc/self/ns/net returns the namespace of the main thread, not
// of whatever thread this goroutine is running on. Make sure we
// use the thread's net namespace since the thread is switching around
return fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
}
func (ns *netNS) Close() error {
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
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Call Close exactly once per netns handle and rely on the closed flag for idempotency
- Do not close the underlying fd from elsewhere (avoid sharing the *os.File outside the library)
- Check for fd leaks/tampering if EBADF appears; audit any code that duplicates or reaps fds
- If this surfaces in tests, ensure teardown order does not close the ns before the library does
Example fix
// before: double close
ns.Close()
err := ns.Close() // already-closed error path
// after: close once, defer handles it
func work(ns nsutil.NetNS) error {
defer ns.Close()
return nil
} Defensive patterns
Strategy: try-catch
Type guard
func isNetnsOpen(ns nsutil.NetNS) bool { return ns != nil && !ns.IsClosed() } Try / catch
if err := ns.Close(); err != nil {
log.Printf("warn: netns close failed for handle: %v (possible double-close or external fd close)", err)
} Prevention
- Close each netns handle exactly once; prefer defer ns.Close() at the point of creation
- Never share or close the underlying *os.File outside the library
- Check errorIfClosed before reusing a handle after Close
- Audit fd handling code that might close foreign descriptors (EBADF source)
When it happens
Trigger: Calling ns.Close() (also invoked via deferred cleanup in NewNS) when ns.file.Close() returns an error — e.g. the file was already closed at the fd level, I/O error, or fd closed elsewhere causing EBADF. Note Close returns errorIfClosed's error first if called twice.
Common situations: Calling Close twice on the same netns handle (second call returns 'netns already closed', not this error); external code closing the same fd; resource-limit related edge cases during heavy churn of namespaces.
Related errors
- mount --make-rshared %s failed: %q
- mount --rbind %s %s failed: %q
- failed to get the current netns: %v
- error from unshare: %v
- failed to bind mount ns at %s: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/dac482ea90d9b2df.
Report an issue: GitHub.