{"record":{"id":"feb0b6aa1674c235","repo":"JuliusBrussee/caveman","slug":"native-runtime-remove-stale-socket-w","errorCode":null,"errorMessage":"native runtime remove stale socket: %w","messagePattern":"native runtime remove stale socket: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/server_unix.go","lineNumber":49,"sourceCode":"// the coding agent or the provider proxy.\nfunc ServeUnix(ctx context.Context, path string, runtime *Runtime) error {\n\tif runtime == nil || runtime.store == nil {\n\t\treturn errors.New(\"native runtime: store is required\")\n\t}\n\tif err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {\n\t\treturn fmt.Errorf(\"native runtime mkdir: %w\", err)\n\t}\n\tif err := os.Chmod(filepath.Dir(path), 0o700); err != nil {\n\t\treturn fmt.Errorf(\"native runtime chmod dir: %w\", err)\n\t}\n\tif _, err := os.Stat(path); err == nil {\n\t\tconn, dialErr := net.DialTimeout(\"unix\", path, 50*time.Millisecond)\n\t\tif dialErr == nil {\n\t\t\t_ = conn.Close()\n\t\t\treturn errors.New(\"native runtime: socket already active\")\n\t\t}\n\t\tif err := os.Remove(path); err != nil {\n\t\t\treturn fmt.Errorf(\"native runtime remove stale socket: %w\", err)\n\t\t}\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"native runtime inspect socket: %w\", err)\n\t}\n\tlistener, err := net.Listen(\"unix\", path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"native runtime listen: %w\", err)\n\t}\n\tdefer listener.Close()\n\tdefer os.Remove(path)\n\tif err := os.Chmod(path, 0o600); err != nil {\n\t\treturn fmt.Errorf(\"native runtime chmod socket: %w\", err)\n\t}\n\tgo func() {\n\t\t<-ctx.Done()\n\t\t_ = listener.Close()\n\t}()\n\tfor {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/proxy/internal/nativeruntime/server_unix.go#L31-L67","documentation":"ServeUnix found an existing filesystem entry at the socket path, verified via a 50ms dial that no live listener answers (stale), and then os.Remove of that stale entry failed. Typically the entry is owned by another user, the directory denies write (unlink) permission, or the entry is a directory rather than a socket file.","triggerScenarios":"Previous crash under a different user left the socket file; socket dir not writable for unlink; path occupied by a real directory; immutable attribute set.","commonSituations":"Running the runtime alternately under sudo and normal user; reusing a system /run path with restrictive permissions.","solutions":["Remove the stale entry as its owner: sudo rm <socket-path>","Give the running user write permission on the socket directory","If the entry is a directory, rmdir it","Clear immutability: sudo chattr -i <socket-path>"],"exampleFix":"# before\nstale socket owned by root -> Error[1078]\n\n# after\nsudo rm /run/caveman/native.sock && systemctl restart caveman-runtime","handlingStrategy":"retry","validationCode":"func staleRemovable(p string) bool {\n    fi, err := os.Stat(p)\n    if err != nil { return false }\n    return fi.Mode()&os.ModeSocket != 0 // only auto-remove socket files, never dirs\n}","typeGuard":null,"tryCatchPattern":"err := nativeruntime.ServeUnix(ctx, path, rt)\nif err != nil && strings.Contains(err.Error(), \"remove stale socket\") {\n    os.Remove(path) // as owner / with privileges, then serve again\n    err = nativeruntime.ServeUnix(ctx, path, rt)\n}","preventionTips":["Stop services cleanly (SIGTERM triggers the deferred socket removal)","Give the service user unlink permission on the socket directory","Clean crash-orphaned sockets in a pre-start ExecStartPre step"],"tags":["unix-socket","stale-state","permissions","nativeruntime"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}