chenhg5/cc-connect · critical
dial: %s
Error message
dial: %s
What it means
runWS dials the TuiTui websocket endpoint /robot/callback/ws with appID.appSecret auth; if the websocket handshake fails, the dialer error is wrapped as "dial: %s" after passing it through core.RedactToken to scrub the app secret from the message. This is the low-level connection error surfaced by connectLoop's reconnect cycle.
Source
Thrown at platform/tuitui/tuitui.go:329
}
slog.Warn("tuitui: websocket disconnected, retrying", "error", err, "backoff", backoff)
select {
case <-ctx.Done():
return
case <-time.After(backoff):
}
backoff *= 2
if backoff > maxReconnectBackoff {
backoff = maxReconnectBackoff
}
}
}
func (p *Platform) runWS(ctx context.Context) error {
wsURL := p.wsBase + "/robot/callback/ws?auth=" + url.QueryEscape(p.appID+"."+p.appSecret)
conn, _, err := websocket.DefaultDialer.DialContext(ctx, wsURL, nil)
if err != nil {
return fmt.Errorf("dial: %s", core.RedactToken(err.Error(), p.appSecret))
}
defer func() { _ = conn.Close() }()
slog.Info("tuitui: websocket connected")
done := make(chan error, 1)
go func() {
for {
_, data, err := conn.ReadMessage()
if err != nil {
done <- err
return
}
p.handleFrame(ctx, conn, data)
}
}()
select {
case <-ctx.Done():View on GitHub (pinned to 4000b2338a)
Solutions
- Check network connectivity and whether the TuiTui endpoint is reachable (the redacted message will indicate DNS vs TLS vs HTTP failure).
- Verify wsBase and appID/appSecret in config — the auth query parameter embeds appID.appSecret and wrong values are rejected at handshake.
- Rely on connectLoop's retry/backoff for transient outages; investigate persistent failures in platform status or proxy settings.
Example fix
// before wsBase = "https://wrong-host.example.com" // dial fails // after wsBase = "https://open.tuitui.example.com" // correct endpoint from platform docs
Defensive patterns
Strategy: retry
Validate before calling
// pre-check endpoint reachability
conn, err := net.DialTimeout("tcp", host, 5*time.Second)
if err != nil {
log.Warn("tuitui endpoint unreachable", "err", err)
} Try / catch
if err := p.Start(handler); err != nil {
log.Error("tuitui start failed", "err", err) // dial errors surface via connectLoop logs
// rely on connectLoop backoff; alert after N consecutive failures
} Prevention
- Monitor connectivity to the TuiTui websocket endpoint from your deployment.
- Keep appID/appSecret valid — handshake auth embeds them.
- Configure proxies/firewalls to allow websocket upgrades.
- Use connectLoop's backoff and alert on sustained reconnect failure instead of crashing.
When it happens
Trigger: websocket.DefaultDialer.DialContext fails: server unreachable, DNS failure, TLS error, non-101 HTTP response (bad path/auth), or context cancellation mid-dial.
Common situations: TuiTui service outage or maintenance; corporate proxy/firewall blocking websocket upgrades; wrong wsBase URL configured; invalid appID/appSecret causing the server to reject the upgrade; network flaps triggering repeated reconnect dials.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- qq: ws connect failed (%s): %w
- wps-agentspace: dial: %w
- wps-agentspace: init: %w
- wecom-ws: ack timeout
- connect permission bridge: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/ea30641ee5cd04d6.
Report an issue: GitHub.