{"record":{"id":"a10378c33d28f6d1","repo":"chenhg5/cc-connect","slug":"bridge-preview-ack-timeout","errorCode":null,"errorMessage":"bridge: preview_ack timeout","messagePattern":"bridge: preview_ack timeout","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/bridge.go","lineNumber":562,"sourceCode":"\t\t\"ref_id\":      refID,\n\t\t\"session_key\": rc.SessionKey,\n\t\t\"reply_ctx\":   rc.ReplyCtx,\n\t\t\"content\":     content,\n\t}); err != nil {\n\t\ta.previewMu.Lock()\n\t\tdelete(a.previewRequests, refID)\n\t\ta.previewMu.Unlock()\n\t\treturn nil, err\n\t}\n\n\tselect {\n\tcase handle := <-ch:\n\t\treturn newBridgeReplyCtx(a, rc.SessionKey, handle), nil\n\tcase <-time.After(10 * time.Second):\n\t\ta.previewMu.Lock()\n\t\tdelete(a.previewRequests, refID)\n\t\ta.previewMu.Unlock()\n\t\treturn nil, fmt.Errorf(\"bridge: preview_ack timeout\")\n\tcase <-ctx.Done():\n\t\ta.previewMu.Lock()\n\t\tdelete(a.previewRequests, refID)\n\t\ta.previewMu.Unlock()\n\t\treturn nil, ctx.Err()\n\t}\n}\n\nfunc (bp *BridgePlatform) DeletePreviewMessage(ctx context.Context, previewHandle any) error {\n\trc, ok := previewHandle.(*bridgeReplyCtx)\n\tif !ok {\n\t\treturn fmt.Errorf(\"bridge: invalid preview handle\")\n\t}\n\ta := bp.server.getAdapter(rc.Platform)\n\tif a == nil || !a.capabilities[\"delete_message\"] {\n\t\treturn ErrNotSupported\n\t}\n\treturn bp.server.sendToAdapter(rc.Platform, map[string]any{","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/bridge.go#L544-L580","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the adapter process/connection is alive and responsive; restart or reconnect it.","Retry the preview request — transient slowness is the most common cause.","Pass a context that is not already near deadline, and surface the error to the user so they can retry.","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."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // barely fits\nhandle, err := p.RequestPreviewMessage(ctx, text)\n// after\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // headroom for slow adapters\nhandle, err := p.RequestPreviewMessage(ctx, text)\nif errors.Is(err, context.DeadlineExceeded) { /* show retry UI */ }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"handle, err := p.RequestPreviewMessage(ctx, text)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), \"preview_ack timeout\") {\n        slog.Warn(\"bridge preview ack timeout, retrying once\")\n        handle, err = p.RequestPreviewMessage(ctx, text)\n    }\n    if err != nil { return fmt.Errorf(\"preview unavailable: %w\", err) }\n}","preventionTips":["Keep the adapter process healthy and monitor its heartbeat before issuing preview requests","Always pass a context with explicit deadline/timeout so cancellation is handled deterministically","Retry once on timeout before surfacing the error to the user","Watch for systematic timeouts — they usually mean the adapter or link is degraded, not transient"],"tags":["bridge","timeout","preview","rpc"],"backgroundTag":"request-timeout","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}