{"record":{"id":"17118c97cbce327b","repo":"hashicorp/nomad","slug":"failed-to-remove-ns-path-s-w","errorCode":null,"errorMessage":"failed to remove ns path %s: %w","messagePattern":"failed to remove ns path (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/lib/nsutil/netns_linux.go","lineNumber":140,"sourceCode":"\twg.Wait()\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create namespace: %v\", err)\n\t}\n\n\treturn GetNS(nsPath)\n}\n\n// UnmountNS unmounts the NS held by the netns object\nfunc UnmountNS(nsPath string) error {\n\t// Only unmount if it's been bind-mounted (don't touch namespaces in /proc...)\n\tif strings.HasPrefix(nsPath, NetNSRunDir) {\n\t\tif err := unix.Unmount(nsPath, unix.MNT_DETACH); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to unmount NS: at %s: %w\", nsPath, err)\n\t\t}\n\n\t\tif err := os.Remove(nsPath); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to remove ns path %s: %w\", nsPath, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":122,"sourceCodeEnd":146,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/lib/nsutil/netns_linux.go#L122-L146","documentation":"After successfully unmounting, UnmountNS removes the namespace file from /var/run/netns with os.Remove. If the removal fails, this error is returned. The mount is gone at this point, but the stale file remains on disk.","triggerScenarios":"unix.Unmount succeeded but os.Remove(nsPath) fails during UnmountNS (via DestroyNetwork) — EACCES due to directory permissions, ENOENT if the file vanished concurrently, or read-only filesystem.","commonSituations":"Two concurrent DestroyNetwork calls racing on the same nsPath; /run mounted read-only after a container state change; wrong ownership/permissions on /run/netns.","solutions":["Serialize teardown so only one caller removes the path (mutex or single owner of the ns lifecycle)","Ignore ENOENT as success if concurrent removal is possible (check errors.Is(err, fs.ErrNotExist))","Ensure the process user has write permission on /run/netns","Verify /run is writable (not mounted read-only)"],"exampleFix":"// before: races report ENOENT\nif err := os.Remove(nsPath); err != nil {\n    return fmt.Errorf(\"failed to remove ns path %s: %w\", nsPath, err)\n}\n// after (caller-side tolerance)\nerr := nsutil.UnmountNS(nsPath)\nif err != nil && !errors.Is(err, fs.ErrNotExist) {\n    return err\n}","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(nsPath); err != nil || fi.IsDir() {\n    return fmt.Errorf(\"invalid ns path %s\", nsPath)\n}","typeGuard":null,"tryCatchPattern":"err := nsutil.UnmountNS(nsPath)\nif err != nil && errors.Is(err, fs.ErrNotExist) {\n    return nil // already removed by a concurrent teardown\n}\nif err != nil {\n    return fmt.Errorf(\"stale ns file at %s: %w\", nsPath, err)\n}","preventionTips":["Serialize DestroyNetwork calls per namespace (single owner/mutex)","Treat ENOENT during cleanup as success","Ensure the process user owns /run/netns or has write access","Keep /run writable; alert on read-only remounts"],"tags":["linux","network-namespace","filesystem","cleanup"],"backgroundTag":"file-remove-failed","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"}