hashicorp/nomad · error

failed to Statfs %q: %v

Error message

failed to Statfs %q: %v

What it means

IsNSorErr validates that a path refers to a namespace file by statfs-ing it and comparing the filesystem magic (PROCFS_MAGIC or NSFS_MAGIC). This error is returned when syscall.Statfs fails on the given path and the path exists — i.e. Statfs failed for a reason other than non-existence, so the path cannot be confirmed as a namespace.

Source

Thrown at client/lib/nsutil/ns_linux.go:131

	NSFS_MAGIC   = unix.NSFS_MAGIC
	PROCFS_MAGIC = unix.PROC_SUPER_MAGIC
)

type NSPathNotExistErr struct{ msg string }

func (e NSPathNotExistErr) Error() string { return e.msg }

type NSPathNotNSErr struct{ msg string }

func (e NSPathNotNSErr) Error() string { return e.msg }

func IsNSorErr(nspath string) error {
	stat := syscall.Statfs_t{}
	if err := syscall.Statfs(nspath, &stat); err != nil {
		if os.IsNotExist(err) {
			err = NSPathNotExistErr{msg: fmt.Sprintf("failed to Statfs %q: %v", nspath, err)}
		} else {
			err = fmt.Errorf("failed to Statfs %q: %v", nspath, err)
		}
		return err
	}

	switch stat.Type {
	case PROCFS_MAGIC, NSFS_MAGIC:
		return nil
	default:
		return NSPathNotNSErr{msg: fmt.Sprintf("unknown FS magic on %q: %x", nspath, stat.Type)}
	}
}

// GetNS returns an object representing the namespace referred to by @path
func GetNS(nspath string) (NetNS, error) {
	err := IsNSorErr(nspath)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check the wrapped errno from the %v: EACCES means fix permissions, ENOTDIR/ENOENT means fix the path
  2. Verify /proc is mounted and readable by the calling user
  3. Confirm the path is the correct /proc/<pid>/ns/net or a valid bind mount of a namespace
  4. If os.IsNotExist was the cause, the error would be NSPathNotExistErr instead — treat this variant as an environment/mount problem

Example fix

// before
ns, err := GetNS("/proc/9999/ns/net") // pid gone, statfs fails
// after
if _, err := os.Stat("/proc/9999/ns/net"); err != nil {
    return fmt.Errorf("netns path unavailable: %w", err)
}
ns, err := GetNS("/proc/9999/ns/net")
Defensive patterns

Strategy: validation

Validate before calling

func validateNSPath(p string) error {
    fi, err := os.Stat(p)
    if err != nil {
        return fmt.Errorf("netns path missing: %w", err)
    }
    if !fi.Mode().IsRegular() && fi.Mode()&os.ModeDevice == 0 && !fi.Mode().IsDir() {
        // proceed; ns files are odd modes, only reject obvious dirs
        _ = fi
    }
    return nil
}

Type guard

func isNSPathNotExistErr(err error) bool {
    _, ok := err.(NSPathNotExistErr)
    return ok
}

Try / catch

if err := IsNSorErr(nspath); err != nil {
    if isNSPathNotExistErr(err) {
        return fmt.Errorf("netns does not exist: %w", err)
    }
    return fmt.Errorf("netns path unusable (check /proc mount & perms): %w", err)
}

Prevention

When it happens

Trigger: Calling IsNSorErr (directly or via GetNS) with a path that exists but cannot be stat'd: permission denied on a parent directory, path is on a broken mount, I/O error, or too many symbolic links.

Common situations: Passing a netns path like /proc/<pid>/ns/net where /proc is not mounted or is mounted with hidepid restrictions; stale bind-mounted ns paths after a container exited (though those usually give NSPathNotExistErr); typo in the path with a dangling mount point.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/f7a21fa4aba1d968. Report an issue: GitHub.