{"record":{"id":"f4de5c3222262623","repo":"JuliusBrussee/caveman","slug":"native-runtime-socket-already-active","errorCode":null,"errorMessage":"native runtime: socket already active","messagePattern":"native runtime: socket already active","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/server_unix.go","lineNumber":46,"sourceCode":"\n// ServeUnix exposes one-request-per-connection JSON over a user-only Unix\n// socket. Runtime errors close or fail-open the individual call; they never stop\n// 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()","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/proxy/internal/nativeruntime/server_unix.go#L28-L64","documentation":"The unix-socket Serve function probes an existing socket path with a 50ms dial before listening. If the dial succeeds, another live runtime owns that socket and Serve refuses to start rather than stealing it. Only when the dial fails is the stale socket file removed and the path reused.","triggerScenarios":"Starting a second runtime instance with the same home directory while the first is still serving; an orchestrator/supervisor restarting the service before the old process fully exited; running two proxy commands concurrently against the same home.","commonSituations":"Development running the daemon twice; systemd/docker restart races where the old process lingers; forking a child that inherits and re-serves the same home path.","solutions":["Find and stop the existing instance (check the run-state file for its PID) before starting a new one","Use a different home directory for the second instance if concurrent runtimes are intended","If truly stale, ensure the old process is killed; the server will then remove the dead socket itself"],"exampleFix":"# before\n$ caveman-proxy serve &   # second instance, same home -> socket already active\n\n# after\n$ pkill -f caveman-proxy || kill $(cat ~/.caveman/runstate/port-*/pid)\n$ caveman-proxy serve &","handlingStrategy":"validation","validationCode":"conn, err := net.DialTimeout(\"unix\", socketPath, 50*time.Millisecond)\nif err == nil {\n    conn.Close()\n    return errors.New(\"another runtime is already serving this home\")\n}","typeGuard":null,"tryCatchPattern":"if err := nativeruntime.Serve(ctx, home, rt); err != nil {\n    if strings.Contains(err.Error(), \"socket already active\") {\n        // stop the existing instance via its run-state PID, then restart\n    }\n}","preventionTips":["Use the run-state file to find and stop the previous instance before restarts","Give concurrent instances separate home directories","Ensure supervisors wait for process exit before restarting"],"tags":["nativeruntime","go","unix-socket","concurrency","startup"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}