chenhg5/cc-connect · error

cloud_web: websocket not connected

Error message

cloud_web: websocket not connected

What it means

wsTransport.Send checks the current connection under a read lock; if t.conn is nil (no active WebSocket), it returns this error instead of attempting a write. Callers sending a message through the cloud-web transport while disconnected get this immediate failure rather than a blocked write.

Source

Thrown at platform/cloud-web/ws.go:272

		if base.Type == "capabilities_changed" {
			var ch wireCapabilitiesChanged
			if err := json.Unmarshal(raw, &ch); err == nil && len(ch.Capabilities) > 0 {
				t.setCaps(capabilitySet(ch.Capabilities))
			}
		}
	default:
		if t.onInbound != nil {
			t.onInbound(raw)
		}
	}
}

func (t *wsTransport) Send(ctx context.Context, msg map[string]any) error {
	t.mu.RLock()
	conn := t.conn
	t.mu.RUnlock()
	if conn == nil {
		return fmt.Errorf("cloud_web: websocket not connected")
	}
	t.writeMu.Lock()
	defer t.writeMu.Unlock()
	return conn.WriteJSON(msg)
}

func (t *wsTransport) waitPreviewAck(refID string, timeout time.Duration) (string, error) {
	ch := make(chan string, 1)
	t.previewMu.Lock()
	t.previewRequests[refID] = ch
	t.previewMu.Unlock()
	defer func() {
		t.previewMu.Lock()
		delete(t.previewRequests, refID)
		t.previewMu.Unlock()
	}()
	select {
	case handle := <-ch:

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Retry after the transport reconnects — check connection state / wait for onConnected before sending
  2. Buffer or queue outbound messages while disconnected and flush on reconnect
  3. Check why the connection is down (see disconnect logs) and restore connectivity/server
  4. Avoid calling Send before Start/connect completes; gate sends on a connected flag

Example fix

// before
if err := t.Send(ctx, msg); err != nil { ... }
// after (retry with backoff while disconnected)
if err := t.Send(ctx, msg); err != nil && strings.Contains(err.Error(), "not connected") {
    time.Sleep(retryDelay)
    err = t.Send(ctx, msg)
}
Defensive patterns

Strategy: retry

Validate before calling

// Guard before sending
func (t *wsTransport) CanSend() bool {
    t.mu.RLock()
    defer t.mu.RUnlock()
    return t.conn != nil
}

Try / catch

// Retry send after reconnect
if err := t.Send(ctx, msg); err != nil {
    if strings.Contains(err.Error(), "not connected") {
        <-t.Connected() // channel closed on reconnect
        err = t.Send(ctx, msg)
    }
}

Prevention

When it happens

Trigger: Send(ctx, msg) is invoked before connectLoop has established a connection, after a disconnect before reconnection completes, or during shutdown after the connection was cleared.

Common situations: Race between a message reply (e.g. streaming card update or preview) and a network drop; engine starts sending before the WebSocket handshake finishes; server outage with queued outbound messages; Stop() already called.

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


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/c10f1cdf9cd8376c. Report an issue: GitHub.