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
- Increase the preview_ack timeout if the network/server is slow
- Check the connection was alive during the request — a disconnect will swallow the ack; reconnect and retry the preview
- Verify the server sends preview_ack with the same correlation id the client registered
- 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
- Size the timeout for worst-case round-trip + server latency
- Verify the server echoes the correlation id in preview_ack
- Check connection liveness before issuing preview requests
- Fall back to a non-preview card path when acks time out
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- wecom-ws: ack timeout
- read register_ack: %w
- cloud_web: ws_url or base_url is required for websocket tran
- cloud_web: preview_ack timeout
- cloud_web: parse register_ack: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/1a6ce39488edde7a.
Report an issue: GitHub.