chenhg5/cc-connect · error

bridge: preview_ack timeout

Error message

bridge: preview_ack timeout

What it means

BridgePlatform.RequestPreviewMessage waits up to 10 seconds for the remote adapter to acknowledge a preview request, cleaning up the pending entry from previewRequests on failure. This error means no ack arrived before the timeout fired, so no preview handle could be created. It protects the bridge from adapters that are slow, hung, or dead.

Source

Thrown at core/bridge.go:562

		"ref_id":      refID,
		"session_key": rc.SessionKey,
		"reply_ctx":   rc.ReplyCtx,
		"content":     content,
	}); err != nil {
		a.previewMu.Lock()
		delete(a.previewRequests, refID)
		a.previewMu.Unlock()
		return nil, err
	}

	select {
	case handle := <-ch:
		return newBridgeReplyCtx(a, rc.SessionKey, handle), nil
	case <-time.After(10 * time.Second):
		a.previewMu.Lock()
		delete(a.previewRequests, refID)
		a.previewMu.Unlock()
		return nil, fmt.Errorf("bridge: preview_ack timeout")
	case <-ctx.Done():
		a.previewMu.Lock()
		delete(a.previewRequests, refID)
		a.previewMu.Unlock()
		return nil, ctx.Err()
	}
}

func (bp *BridgePlatform) DeletePreviewMessage(ctx context.Context, previewHandle any) error {
	rc, ok := previewHandle.(*bridgeReplyCtx)
	if !ok {
		return fmt.Errorf("bridge: invalid preview handle")
	}
	a := bp.server.getAdapter(rc.Platform)
	if a == nil || !a.capabilities["delete_message"] {
		return ErrNotSupported
	}
	return bp.server.sendToAdapter(rc.Platform, map[string]any{

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the adapter process/connection is alive and responsive; restart or reconnect it.
  2. Retry the preview request — transient slowness is the most common cause.
  3. Pass a context that is not already near deadline, and surface the error to the user so they can retry.
  4. If the 10s budget is systematically too small for your deployment, increase the timeout constant in core/bridge.go or shorten the round trip by moving the adapter closer.

Example fix

// before
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // barely fits
handle, err := p.RequestPreviewMessage(ctx, text)
// after
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // headroom for slow adapters
handle, err := p.RequestPreviewMessage(ctx, text)
if errors.Is(err, context.DeadlineExceeded) { /* show retry UI */ }
Defensive patterns

Strategy: try-catch

Try / catch

handle, err := p.RequestPreviewMessage(ctx, text)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), "preview_ack timeout") {
        slog.Warn("bridge preview ack timeout, retrying once")
        handle, err = p.RequestPreviewMessage(ctx, text)
    }
    if err != nil { return fmt.Errorf("preview unavailable: %w", err) }
}

Prevention

When it happens

Trigger: Calling RequestPreviewMessage when the connected adapter never sends a preview_ack for the refID within 10s, when the adapter process has stalled without the connection dropping, or when the caller's ctx outlives the 10s timer but the adapter is unresponsive.

Common situations: A bridged platform client (e.g. the desktop app side of the bridge) froze or was suspended mid-request; network latency pushed ack turnaround past 10s; the adapter received the request but crashed before replying; a slow agent backend delayed the adapter's response.

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/a10378c33d28f6d1. Report an issue: GitHub.