sipeed/picoclaw · error

failed to stat local command %q: %w

Error message

failed to stat local command %q: %w

What it means

While validating a path-like stdio command, os.Stat failed with something other than ErrNotExist (helpers.go:315-320): permission denied on a parent directory in the path, a path that exceeds filesystem limits, or an I/O error from the underlying filesystem. The raw stat error is preserved via %w so errno detail survives.

Source

Thrown at cmd/picoclaw/internal/mcp/helpers.go:319

	}
	if strings.HasPrefix(path, "~/") || strings.HasPrefix(path, "~\\") {
		return filepath.Join(home, path[2:])
	}
	return path
}

func validateLocalCommandPath(command string) error {
	if !isLocalCommandPath(command) {
		return nil
	}

	path := expandHomePath(command)
	info, err := os.Stat(path)
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			return fmt.Errorf("local command %q does not exist", command)
		}
		return fmt.Errorf("failed to stat local command %q: %w", command, err)
	}
	if info.IsDir() {
		return fmt.Errorf("local command %q is a directory", command)
	}
	if runtime.GOOS != "windows" && info.Mode()&0o111 == 0 {
		return fmt.Errorf("local command %q is not executable", command)
	}
	return nil
}

func defaultServerProbe(
	ctx context.Context,
	name string,
	server config.MCPServerConfig,
	workspacePath string,
) (probeResult, error) {
	mgr := picomcp.NewManager()
	defer func() { _ = mgr.Close() }()

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Grant search permission on every parent directory: chmod +x on each path component (or adjust ownership)
  2. Shorten or relocate the path — install the binary on PATH and reference it by bare name, which skips path validation entirely
  3. If the path sits on a network mount, wait for it to become healthy or copy the binary to local disk

Example fix

# before: /opt/tools is not traversable by $USER
picoclaw mcp add s /opt/tools/server
# after
sudo chmod o+x /opt/tools
picoclaw mcp add s /opt/tools/server
Defensive patterns

Strategy: validation

Validate before calling

path=./tools/mcp-serve
if ! out=$(stat -L "$path" 2>&1); then
  echo "cannot stat $path: $out" >&2   # surfaces EACCES/ENAMETOOLONG/EIO before picoclaw does
  exit 1
fi
picoclaw mcp add s "$path"

Try / catch

if err := addCmd.Execute(); err != nil {
	if strings.Contains(err.Error(), "failed to stat local command") {
		// os.Stat error is wrapped with %w: check fs.ErrPermission first
		if errors.Is(err, fs.ErrPermission) {
			fmt.Fprintln(os.Stderr, "fix search (x) permission on parent directories")
		}
		return err
	}
}

Prevention

When it happens

Trigger: A parent directory in the path lacks execute/search permission for the current user; an extremely long path; stat on a flaky network mount (EIO, ESTALE).

Common situations: Running under a restricted service account; paths under another user's home; NFS/FUSE mounts during hiccups; macOS privacy controls (TCC) denying access to certain folders.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/0d8263352d54b68f. Report an issue: GitHub.