{"record":{"id":"9157280305c361eb","repo":"gastownhall/beads","slug":"server-doltserver-dial-w","errorCode":null,"errorMessage":"server: DoltServer.Dial: %w","messagePattern":"server: DoltServer\\.Dial: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/server/doltserver.go","lineNumber":427,"sourceCode":"\treturn retErr\n}\n\nfunc (s *DoltServer) Running(_ context.Context) bool {\n\tif s.egCtx == nil {\n\t\treturn false\n\t}\n\treturn s.egCtx.Err() == nil\n}\n\nfunc (s *DoltServer) Dial(ctx context.Context) (net.Conn, error) {\n\tnetwork, addr := \"tcp\", net.JoinHostPort(s.config.Host(), strconv.Itoa(s.config.Port()))\n\tif sock := s.config.Socket(); sock != \"\" {\n\t\tnetwork, addr = \"unix\", sock\n\t}\n\tvar d net.Dialer\n\tconn, err := d.DialContext(ctx, network, addr)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"server: DoltServer.Dial: %w\", err)\n\t}\n\tif tc, ok := conn.(*net.TCPConn); ok {\n\t\t_ = tc.SetKeepAlive(true)\n\t\t_ = tc.SetKeepAlivePeriod(s.keepAlivePeriod)\n\t}\n\treturn conn, nil\n}\n","sourceCodeStart":409,"sourceCodeEnd":435,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/server/doltserver.go#L409-L435","documentation":"DoltServer.Dial dials the running Dolt server over TCP or a Unix socket and wraps any net.Dialer.DialContext failure. It surfaces the OS-level network error (connection refused, no such file, timeout) with the server: DoltServer.Dial prefix.","triggerScenarios":"Calling Dial (directly or via waitReady) when the server is not yet listening, the configured port/socket path is wrong, the socket file was deleted, or the context deadline expires before the TCP/socket handshake.","commonSituations":"Client dialing before the server finished starting (waitReady race), port already reassigned after a crash, socket path mismatch between config and caller, firewall or container network isolation blocking localhost TCP.","solutions":["Confirm the server is Running and check its actual listening address (config.Port()/Socket()) matches what Dial uses","Use waitReady with a generous retry/backoff instead of dialing immediately after Start","For unix sockets, verify the socket file exists (os.Stat) and the path is < 108 chars with correct permissions","Test connectivity directly: `nc -z localhost <port>` or `nc -U <socket>` to isolate OS-level failures"],"exampleFix":"// before\nconn, err := server.Dial(ctx)\nif err != nil { return err }\n// after\nerr := waitReady(ctx, server, 30*time.Second) // retry dial until server listens\nif err != nil { return fmt.Errorf(\"dolt server never became ready: %w\", err) }","handlingStrategy":"retry","validationCode":"// check reachability before Dial\naddr := fmt.Sprintf(\"%s:%d\", host, port)\nif sock != \"\" {\n    if _, err := os.Stat(sock); err != nil { return fmt.Errorf(\"socket %s missing: %w\", sock, err) }\n} else if conn, err := net.DialTimeout(\"tcp\", addr, time.Second); err != nil {\n    return fmt.Errorf(\"%s unreachable: %w\", addr, err)\n} else { conn.Close() }","typeGuard":null,"tryCatchPattern":"var conn net.Conn\nerr := retry.Do(func() (err error) {\n    conn, err = server.Dial(ctx)\n    return err\n}, retry.Delay(200*time.Millisecond), retry.Attempts(10), retry.Context(ctx))\nif err != nil { return fmt.Errorf(\"dolt server not reachable: %w\", err) }\ndefer conn.Close()","preventionTips":["Always start via waitReady with backoff instead of immediate Dial","Log the server's effective port/socket at Start and reuse it for Dial","Keep socket paths short (<108 chars) and in a stable, user-writable directory","Add a health Dial to readiness probes in containers"],"tags":["go","network","tcp","unix-socket","dial"],"backgroundTag":"connection-refused","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}