{"record":{"id":"2422b811b0510585","repo":"wavetermdev/waveterm","slug":"failed-to-connect-to-tcp-or-unix-domain-socket-tc","errorCode":null,"errorMessage":"failed to connect to tcp or unix domain socket: tcp err:%w: unix socket err: %w","messagePattern":"failed to connect to tcp or unix domain socket: tcp err:%w: unix socket err: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshutil.go","lineNumber":203,"sourceCode":"\treturn net.DialTCP(\"tcp\", nil, addr)\n}\n\nfunc SetupDomainSocketRpcClient(sockName string, serverImpl ServerImpl, debugName string) (*WshRpc, error) {\n\tsockName = wavebase.ExpandHomeDirSafe(sockName)\n\tresolvedPath, err := filepath.EvalSymlinks(sockName)\n\tif err == nil {\n\t\tsockName = resolvedPath\n\t}\n\tif !filepath.IsAbs(sockName) {\n\t\treturn nil, fmt.Errorf(\"socket path must be absolute: %s\", sockName)\n\t}\n\tconn, tcpErr := tryTcpSocket(sockName)\n\tvar unixErr error\n\tif tcpErr != nil {\n\t\tconn, unixErr = net.Dial(\"unix\", sockName)\n\t}\n\tif tcpErr != nil && unixErr != nil {\n\t\treturn nil, fmt.Errorf(\"failed to connect to tcp or unix domain socket: tcp err:%w: unix socket err: %w\", tcpErr, unixErr)\n\t}\n\trtn, errCh, err := SetupConnRpcClient(conn, serverImpl, debugName)\n\tgo func() {\n\t\tdefer func() {\n\t\t\tpanichandler.PanicHandler(\"SetupDomainSocketRpcClient:closeConn\", recover())\n\t\t}()\n\t\tdefer conn.Close()\n\t\terr := <-errCh\n\t\tif err != nil && err != io.EOF {\n\t\t\tlog.Printf(\"error in domain socket connection: %v\\n\", err)\n\t\t}\n\t}()\n\treturn rtn, err\n}\n\nfunc MakeClientJWTToken(rpcCtx wshrpc.RpcContext) (string, error) {\n\tif wavebase.IsDevMode() {\n\t\tif rpcCtx.IsRouter && (rpcCtx.RouteId != \"\" || rpcCtx.ProcRoute) {","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshutil.go#L185-L221","documentation":"SetupDomainSocketRpcClient first tries a TCP dial to the path and falls back to a unix domain socket dial. If BOTH attempts fail, it combines both underlying errors into this single wrapped error, meaning nothing is listening at (or reachable via) the given socket address.","triggerScenarios":"Neither tryTcpSocket(sockName) nor net.Dial(\"unix\", sockName) succeeds — the socket file does not exist, the server process is not running, stale socket file after a crash, or permission denied on the socket.","commonSituations":"Wave server not started yet; leftover stale socket file; wrong socket path in config; permissions changed on the socket directory; server listening on a different version's socket path.","solutions":["Confirm the server process is running and has created the socket file (ls -l on the path).","Remove stale socket files and restart the server.","Verify the socket path matches what the server actually listens on.","Check permissions on the socket file and its parent directories.","Read the wrapped tcpErr/unixErr details — ECONNREFUSED vs ENOENT vs EACCES point to different fixes."],"exampleFix":"// before\nconn, _, err := wshutil.SetupDomainSocketRpcClient(ctx, impl, sock, \"dbg\")\nif err != nil { return err }\n// after\nconn, _, err := wshutil.SetupDomainSocketRpcClient(ctx, impl, sock, \"dbg\")\nif err != nil {\n    if errors.Is(err, os.ErrNotExist) {\n        return fmt.Errorf(\"server not running at %s: %w\", sock, err)\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"if _, err := os.Stat(sockName); err != nil {\n    return fmt.Errorf(\"socket file %s not found; is the server running?\", sockName)\n}","typeGuard":null,"tryCatchPattern":"var conn *wshutil.WshConn\nvar err error\nfor i := 0; i < 5; i++ {\n    conn, _, err = SetupDomainSocketRpcClient(ctx, impl, sockName, dbg)\n    if err == nil { break }\n    time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)\n}\nif err != nil { return fmt.Errorf(\"server unreachable at %s: %w\", sockName, err) }","preventionTips":["Check the wrapped tcp/unix errors to distinguish ENOENT vs ECONNREFUSED vs EACCES","Remove stale socket files before restarting the server","Retry with backoff on startup while the server creates the socket","Verify server socket path config matches the client's path"],"tags":["go","network","unix-socket","connection"],"backgroundTag":"connection-refused","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}