chenhg5/cc-connect · error

cloud_web: preview_ack timeout

Error message

cloud_web: preview_ack timeout

What it means

waitPreviewAck registers a handler for a preview_ack frame and waits on a channel with a fixed timeout; if no matching preview_ack arrives before the deadline, it returns this error and the caller gives up on obtaining the card handle. The cloud-web peer never confirmed the preview/card-creation request in time.

Source

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

	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:
		return handle, nil
	case <-time.After(timeout):
		return "", fmt.Errorf("cloud_web: preview_ack timeout")
	}
}

func resolveWSURL(baseURL, wsURL string) string {
	if strings.TrimSpace(wsURL) != "" {
		return wsURL
	}
	base := strings.TrimRight(strings.TrimSpace(baseURL), "/")
	if base == "" {
		return ""
	}
	if strings.HasPrefix(base, "https://") {
		return "wss://" + strings.TrimPrefix(base, "https://") + defaultWSPath
	}
	if strings.HasPrefix(base, "http://") {
		return "ws://" + strings.TrimPrefix(base, "http://") + defaultWSPath
	}
	if strings.Contains(base, "://") {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Increase the preview_ack timeout if the network/server is slow
  2. Check the connection was alive during the request — a disconnect will swallow the ack; reconnect and retry the preview
  3. Verify the server sends preview_ack with the same correlation id the client registered
  4. Add retry logic around preview card creation; surface the timeout to the user as a transient failure

Example fix

// before
handle, err := t.waitPreviewAck(ctx, id, 3*time.Second)
// after (retry once on timeout)
handle, err := t.waitPreviewAck(ctx, id, 3*time.Second)
if err != nil {
    handle, err = t.waitPreviewAck(ctx, id, 10*time.Second)
}
Defensive patterns

Strategy: retry

Try / catch

// Retry the preview request with backoff on timeout
handle, err := waitPreviewAck(ctx, id, timeout)
if err != nil && strings.Contains(err.Error(), "preview_ack timeout") {
    select {
    case <-ctx.Done():
    case <-time.After(backoff):
        handle, err = waitPreviewAck(ctx, id, timeout*2)
    }
}

Prevention

When it happens

Trigger: The select on `<-ch` times out because the server never sent a preview_ack for the requested preview id within `timeout`: request lost, server busy, connection dropped mid-request, or the ack id doesn't match.

Common situations: Slow or overloaded cloud-web hub; connection died right after sending the preview request so the ack never arrives; server doesn't implement the preview_ack flow or mismatches the correlation id; timeout configured too aggressively for a high-latency network.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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