seaweedfs/seaweedfs · error

master process can not start child process: %s

Error message

master process can not start child process: %s

What it means

runFuse in weed/command/fuse_std.go parses FUSE helper-style options (space/dash/comma separated name=value pairs, e.g. `weed fuse /mnt/sw -o filer=localhost:8888,readOnly=true`) before daemonizing into a master/child pair and calling runMount. In master mode the helper resolves its own executable with os.Executable() and re-execs it as a child with `-o child=<pid>` appended; this panic means os.StartProcess failed, i.e. the weed binary could not be exec'd again. Typical errno causes: ENOENT (binary deleted or renamed over after start), EACCES (exec bit lost, or binary sits on a noexec mount), EAGAIN (RLIMIT_NPROC or cgroup pids.max exhausted), ETXTBSY (binary being rewritten concurrently), plus SELinux/apparmor/seccomp denials.

Source

Thrown at weed/command/fuse_std.go:322

		arg0, err := os.Executable()
		if err != nil {
			panic(err)
		}

		// pass our PID to the child process
		pid := os.Getpid()
		argv := append(os.Args, "-o", "child="+strconv.Itoa(pid))

		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGTERM)

		attr := os.ProcAttr{}
		attr.Env = os.Environ()

		child, err := os.StartProcess(arg0, argv, &attr)

		if err != nil {
			panic(fmt.Errorf("master process can not start child process: %s", err))
		}

		err = child.Release()

		if err != nil {
			panic(fmt.Errorf("master process can not release child process: %s", err))
		}

		select {
		case <-c:
			return true
		}
	}

	if fusermountPath != "" {
		if err := os.Setenv("PATH", fusermountPath); err != nil {
			panic(fmt.Errorf("setenv: %s", err))
		}

View on GitHub (pinned to 1c926e8fac)

Solutions

  1. Confirm the binary resolves and is executable: ls -l $(command -v weed) and test -x
  2. Invoke weed via a stable absolute path from a location that is not rewritten during deploys
  3. Raise process limits (ulimit -u, cgroup pids.max) if fork fails with 'resource temporarily unavailable'
  4. Check for noexec mount flags and SELinux/apparmor denials on the binary path
  5. Bypass the re-exec entirely with `weed mount -dir=... -filer=...`, which mounts directly

Example fix

// before
/tmp/deploy-old/weed fuse /mnt/sw -o filer=localhost:8888   # binary path replaced/deleted at deploy time

// after
/opt/seaweedfs/bin/weed fuse /mnt/sw -o filer=localhost:8888 # stable absolute path, exec bit intact
Defensive patterns

Strategy: validation

Validate before calling

# bash: verify the helper can re-exec itself before mounting
exe="$(command -v weed)"
[ -n "$exe" ] && [ -x "$exe" ] || { echo "weed binary not executable: $exe" >&2; exit 1; }
readlink -f "$exe" >/dev/null || exit 1

Type guard

func canReexecSelf() error {
	exe, err := os.Executable()
	if err != nil {
		return err
	}
	fi, err := os.Stat(exe)
	if err != nil {
		return fmt.Errorf("cannot stat %s: %w", exe, err)
	}
	if fi.IsDir() || fi.Mode()&0o111 == 0 {
		return fmt.Errorf("%s is not executable", exe)
	}
	return nil
}

Prevention

When it happens

Trigger: Package upgrade renames a new weed binary over the running path before the re-exec; container with pids.max nearly exhausted; weed placed on a noexec filesystem or with chmod -x; hardened seccomp profile blocking fork/exec in CI.

Common situations: CI containers with tight pid limits; deployment scripts that mv/rm the binary then start mounts from the old path; security-hardened hosts denying exec of non-standard paths.

Related errors


AI-assisted analysis of seaweedfs/seaweedfs@1c926e8fac (2026-08-15). Data as JSON: /api/errors/e8445b0bd2b3baaf. Report an issue: GitHub.