dagger/dagger · error

failed to unshare mount namespace: %w

Error message

failed to unshare mount namespace: %w

What it means

Before setns into a new mount namespace, the kernel requires the thread not share filesystem attributes (CLONE_FS) with another thread; the worker calls unix.Unshare(unix.CLONE_FS) first. This error means that unshare syscall failed, so joining the target mount namespace was aborted.

Source

Thrown at engine/engineutil/linux_namespace.go:390

func (nsw *dynamicNamespaceWorker) enterNamespaces() error {
	if nsw.inNamespace {
		return nil
	}

	runtime.LockOSThread()

	for _, ns := range nsw.namespaces {
		if ns.setNSArg == unix.CLONE_NEWNS {
			// Unshare FS metadata first, otherwise setns to another mount
			// namespace doesn't work.
			//
			// Possibly relevant Kernel docs:
			//
			// For security reasons, a process can't join a new mount namespace if it
			// is sharing filesystem-related attributes (the attributes whose sharing
			// is controlled by the clone(2) CLONE_FS flag) with another process.
			if err := unix.Unshare(unix.CLONE_FS); err != nil {
				return fmt.Errorf("failed to unshare mount namespace: %w", err)
			}
		}

		if err := unix.Setns(int(ns.targetFile.Fd()), ns.setNSArg); err != nil {
			return fmt.Errorf("failed to enter namespace: %w", err)
		}
	}
	nsw.inNamespace = true
	return nil
}

// leaveNamespaces exits all namespaces and returns to host
func (nsw *dynamicNamespaceWorker) leaveNamespaces() error {
	if !nsw.inNamespace {
		return nil
	}

	for _, ns := range nsw.namespaces {

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Ensure the process has CAP_SYS_ADMIN in the target namespace's user namespace
  2. Check seccomp profile allows unshare (default Docker/containerd seccomp blocks it in some configs)
  3. Update the kernel; very old kernels had restrictions on unshare from multithreaded processes
  4. Drop the mount namespace from the job if only network namespace isolation is needed

Example fix

// before
if err := unix.Unshare(unix.CLONE_FS); err != nil { return err } // EPERM under restrictive seccomp
// after
if err := unix.Unshare(unix.CLONE_FS); err != nil {
    return fmt.Errorf("unshare(CLONE_FS) failed (needs CAP_SYS_ADMIN and seccomp allowing unshare): %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure unshare is permitted before submitting mount-ns jobs
if err := unix.Unshare(unix.CLONE_FS); err != nil {
    return fmt.Errorf("environment cannot unshare CLONE_FS: %w", err)
}
unix.Setns /* restore as needed */

Try / catch

if err := gwp.RunInNamespaces(ctx, id, nss, fn); err != nil {
    if strings.Contains(err.Error(), "failed to unshare mount namespace") {
        // run with CAP_SYS_ADMIN and a seccomp profile allowing unshare, or drop MountNamespace from the job
    }
}

Prevention

When it happens

Trigger: unix.Unshare(unix.CLONE_FS) returns an error while entering a MountNamespace entry, typically EINVAL/EPERM from kernel restrictions.

Common situations: Thread's fs attributes are shared (CLONE_FS) and the kernel disallows unshare in this context; unprivileged environment without CAP_SYS_ADMIN; kernel/seccomp blocking unshare syscall (common in restricted containers); Go runtime thread state interactions.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/5c698c67e51c03a1. Report an issue: GitHub.