JuliusBrussee/caveman · error
native runtime chmod socket: %w
Error message
native runtime chmod socket: %w
What it means
Returned when os.Chmod(path, 0o600) fails on the freshly created Unix socket. The listener already bound successfully; this step locks the socket to the owning user. It fails when the socket file disappears between listen and chmod or the kernel/FS rejects mode changes on sockets.
Source
Thrown at proxy/internal/nativeruntime/server_unix.go:61
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()
defer os.Remove(path)
if err := os.Chmod(path, 0o600); err != nil {
return fmt.Errorf("native runtime chmod socket: %w", err)
}
go func() {
<-ctx.Done()
_ = listener.Close()
}()
for {
conn, err := listener.Accept()
if err != nil {
if ctx.Err() != nil {
return nil
}
return fmt.Errorf("native runtime accept: %w", err)
}
go serveConn(ctx, conn, runtime)
}
}
View on GitHub (pinned to 27d5a3981a)
Solutions
- Ensure only one instance serves a given home directory at a time (single-flight lock or distinct homes)
- Move the socket onto a normal local filesystem (not NFS/FUSE) by relocating home
- If a cleanup daemon is deleting the socket, exclude the socket path from it
- Retry Serve after confirming the socket path is stable
Example fix
// before: two goroutines/processes sharing one home — loser's stale-cleanup unlinks winner's socket
err := nativeruntime.Serve(ctx, sharedHome, rt)
// after: serialize startup per home (e.g. a lock file) so only one server owns the socket path
if err := acquireHomeLock(sharedHome); err != nil { return err }
err := nativeruntime.Serve(ctx, sharedHome, rt) Defensive patterns
Strategy: validation
Validate before calling
// Ensure exclusive ownership of the socket path before Serve
if conn, err := net.Dial("unix", sockPath); err == nil {
_ = conn.Close()
return errors.New("socket in use; another instance is running")
} Try / catch
if err := nativeruntime.Serve(ctx, home, rt); err != nil {
if errors.Is(err, syscall.ENOENT) && strings.Contains(err.Error(), "chmod socket") {
// socket vanished between listen and chmod — retry once after a beat
time.Sleep(100 * time.Millisecond)
err = nativeruntime.Serve(ctx, home, rt)
}
} Prevention
- Serialize startup with a lock file per home so concurrent cleans cannot race the chmod
- Exclude the socket directory from tmp-cleaners and backup agents
- Keep home on a local filesystem (ext4/apfs), not NFS/FUSE mounts
When it happens
Trigger: Calling Serve on Unix where another process (a concurrent instance or an aggressive cleaner) unlinks the socket file in the window between net.Listen and os.Chmod, or the socket lives on a filesystem that refuses chmod on socket inodes (some FUSE/network mounts).
Common situations: Two caveman instances racing on the same home — the loser's stale-socket cleanup removed the winner's new socket; tmp-reaper daemons deleting files in the home directory; home on NFS or a container volume with restricted ioctl support.
Related errors
- native runtime mkdir: %w
- native runtime chmod dir: %w
- native runtime remove stale socket: %w
- native runtime inspect socket: %w
- native runtime: socket already active
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/7de5d306c627fd18.
Report an issue: GitHub.