JuliusBrussee/caveman · error

native runtime chmod dir: %w

Error message

native runtime chmod dir: %w

What it means

ServeUnix enforces 0700 on the socket's parent directory after creating it, because the socket itself carries no other access control until it is chmod'd — a group/world-readable directory would let other local users connect to the runtime. Chmod failure means wrong ownership or a filesystem that does not support mode changes.

Source

Thrown at proxy/internal/nativeruntime/server_unix.go:40

}

// Serve binds runtime transport for current platform.
func Serve(ctx context.Context, home string, runtime *Runtime) error {
	return ServeUnix(ctx, SocketPath(home), runtime)
}

// ServeUnix exposes one-request-per-connection JSON over a user-only Unix
// socket. Runtime errors close or fail-open the individual call; they never stop
// the coding agent or the provider proxy.
func ServeUnix(ctx context.Context, path string, runtime *Runtime) error {
	if runtime == nil || runtime.store == nil {
		return errors.New("native runtime: store is required")
	}
	if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
		return fmt.Errorf("native runtime mkdir: %w", err)
	}
	if err := os.Chmod(filepath.Dir(path), 0o700); err != nil {
		return fmt.Errorf("native runtime chmod dir: %w", err)
	}
	if _, err := os.Stat(path); err == nil {
		conn, dialErr := net.DialTimeout("unix", path, 50*time.Millisecond)
		if dialErr == nil {
			_ = conn.Close()
			return errors.New("native runtime: socket already active")
		}
		if err := os.Remove(path); err != nil {
			return fmt.Errorf("native runtime remove stale socket: %w", err)
		}
	} else if !os.IsNotExist(err) {
		return fmt.Errorf("native runtime inspect socket: %w", err)
	}
	listener, err := net.Listen("unix", path)
	if err != nil {
		return fmt.Errorf("native runtime listen: %w", err)
	}
	defer listener.Close()

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. chown the socket directory to the runtime user and chmod 700 manually
  2. Delete the pre-existing directory so ServeUnix recreates it as the running user
  3. Use a local POSIX filesystem for the socket directory

Example fix

# before
sudo mkdir -p /run/caveman   # owned by root -> Error[1077]

# after
sudo chown caveman:caveman /run/caveman && sudo chmod 700 /run/caveman
Defensive patterns

Strategy: validation

Validate before calling

func socketDirTight(p string) bool {
    fi, err := os.Stat(filepath.Dir(p))
    return err == nil && fi.IsDir() && fi.Mode().Perm() == 0o700
}

Prevention

When it happens

Trigger: Socket dir pre-created by root while the runtime runs unprivileged; directory on FAT/CIFS or other chmod-ignoring filesystem.

Common situations: Installers creating dirs as root; shared or foreign-mounted volumes.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/15a6e596400e3c9d. Report an issue: GitHub.