{"record":{"id":"a147b8077a2a2b77","repo":"wavetermdev/waveterm","slug":"failed-to-listen-on-domain-socket-w","errorCode":null,"errorMessage":"failed to listen on domain socket: %w","messagePattern":"failed to listen on domain socket: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/jobmanager/jobmanager.go","lineNumber":392,"sourceCode":"\tlog.Printf(\"StartStream: streamid=%s rwnd=%d streaming started\\n\", jm.pendingStreamMeta.Id, jm.pendingStreamMeta.RWnd)\n\tjm.pendingStreamMeta = nil\n\treturn nil\n}\n\nfunc MakeJobDomainSocket(clientId string, jobId string) error {\n\tsocketDir := filepath.Join(\"/tmp\", fmt.Sprintf(\"waveterm-%d\", os.Getuid()))\n\terr := os.MkdirAll(socketDir, 0700)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create socket directory: %w\", err)\n\t}\n\n\tsocketPath := wavebase.GetRemoteJobSocketPath(jobId)\n\n\tos.Remove(socketPath)\n\n\tlistener, err := net.Listen(\"unix\", socketPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to listen on domain socket: %w\", err)\n\t}\n\n\tgo func() {\n\t\tdefer func() {\n\t\t\tpanichandler.PanicHandler(\"MakeJobDomainSocket:accept\", recover())\n\t\t\tlistener.Close()\n\t\t\tos.Remove(socketPath)\n\t\t}()\n\t\tfor {\n\t\t\tconn, err := listener.Accept()\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"error accepting connection: %v\\n\", err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tgo handleJobDomainSocketClient(conn)\n\t\t}\n\t}()\n","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/jobmanager/jobmanager.go#L374-L410","documentation":"MakeJobDomainSocket removes any stale socket at wavebase.GetRemoteJobSocketPath(jobId) and then binds a unix listener with net.Listen(\"unix\", socketPath). This error wraps the net.Listen failure. It means the process could not bind the domain socket path — permissions, path length, directory issues, or address-in-use.","triggerScenarios":"net.Listen(\"unix\", socketPath) returns an error: socket directory unwritable, path exceeds unix socket 108-byte limit, stale socket not removable, another live process already bound (EADDRINUSE), or filesystem does not support unix sockets.","commonSituations":"Job id producing a path longer than sun_path (108 chars); another waveterm job process still holding the socket; /tmp mounted noexec/nodev in some setups; running as different uid than the directory owner; running in an environment without unix socket support (some sandboxes).","solutions":["Check for a live process holding the socket: lsof /tmp/waveterm-<uid>/<jobId> and kill the stale job","Shorten the jobId/socket path if the absolute path exceeds 108 characters (EINVAL/ENAMETOOLONG)","Ensure /tmp/waveterm-<uid> is owned by and writable by the current uid (0700)","Manually remove the stale socket file and retry; verify the filesystem supports AF_UNIX sockets"],"exampleFix":"// before\nlistener, err := net.Listen(\"unix\", socketPath)\nif err != nil {\n    return fmt.Errorf(\"failed to listen on domain socket: %w\", err)\n}\n// after\nlistener, err := net.Listen(\"unix\", socketPath)\nif err != nil {\n    if errors.Is(err, syscall.EADDRINUSE) {\n        os.Remove(socketPath)\n        listener, err = net.Listen(\"unix\", socketPath)\n    }\n    if err != nil {\n        return fmt.Errorf(\"failed to listen on domain socket %s: %w\", socketPath, err)\n    }\n}","handlingStrategy":"retry","validationCode":"socketPath := wavebase.GetRemoteJobSocketPath(jobId)\nif len(socketPath) >= 108 {\n    return fmt.Errorf(\"socket path too long (%d chars)\", len(socketPath))\n}\nif fi, err := os.Lstat(socketPath); err == nil {\n    os.Remove(socketPath) // stale socket\n}","typeGuard":null,"tryCatchPattern":"if err := MakeJobDomainSocket(clientId, jobId); err != nil {\n    if strings.HasPrefix(err.Error(), \"failed to listen on domain socket\") {\n        if strings.Contains(errors.Unwrap(err).Error(), \"address already in use\") {\n            // find and stop the stale job process, then retry\n        }\n    }\n    return err\n}","preventionTips":["Keep job ids short so the socket path stays under 108 characters","Always unlink stale sockets before binding (the code does; keep that behavior)","Detect leftover job processes with lsof/ss before restart","Verify unix socket support and permissions in sandboxed/container environments"],"tags":["go","unix-socket","network","permissions","eaddrinuse"],"backgroundTag":"unix-socket-bind-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}