{"record":{"id":"0dc79bc10ffa1a36","repo":"chenhg5/cc-connect","slug":"googlechat-invalid-preview-handle-type-t","errorCode":null,"errorMessage":"googlechat: invalid preview handle type %T","messagePattern":"googlechat: invalid preview handle type %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/googlechat/streaming.go","lineNumber":81,"sourceCode":"}\n\n// buildUpdateRequest builds the PATCH URL and JSON body to update a message's text.\nfunc buildUpdateRequest(msgName, content string) (string, []byte, error) {\n\tu := chatAPIBase + msgName + \"?updateMask=text\"\n\tb, err := json.Marshal(map[string]any{\"text\": content})\n\tif err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"googlechat: marshal update body: %w\", err)\n\t}\n\treturn u, b, nil\n}\n\n// UpdateMessage patches the preview message text in place. The engine passes the\n// handle returned by SendPreviewStart (not the reply context). Implements\n// core.MessageUpdater.\nfunc (p *Platform) UpdateMessage(ctx context.Context, handle any, content string) error {\n\th, ok := handle.(*previewHandle)\n\tif !ok {\n\t\treturn fmt.Errorf(\"googlechat: invalid preview handle type %T\", handle)\n\t}\n\turl, body, err := buildUpdateRequest(h.name, content)\n\tif err != nil {\n\t\treturn err\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPatch, url, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"googlechat: build update request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tresp, err := p.doRequest(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif _, err := io.Copy(io.Discard, resp.Body); err != nil {\n\t\t_ = resp.Body.Close()\n\t\treturn fmt.Errorf(\"googlechat: drain update response body: %w\", err)\n\t}","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/googlechat/streaming.go#L63-L99","documentation":"This error is returned by UpdateMessage when the `handle` argument passed to it is not a *previewHandle — the concrete type returned by SendPreviewStart. The engine is expected to pass the handle from SendPreviewStart through unchanged (it implements core.MessageUpdater); anything else (replyContext, a string, nil, a handle from another platform) fails this type assertion. The %T verb reports the actual received type to aid debugging.","triggerScenarios":"UpdateMessage(ctx, handle, content) is called with a value whose dynamic type is not *googlechat.previewHandle: a cached reply context, a plain string message name, a nil interface, or a preview handle produced by a different platform adapter.","commonSituations":"Custom engine code or plugins that store the reply context instead of the SendPreviewStart return value; mixing handles across platforms (e.g. a feishu handle routed to googlechat); a refactor that changed the handle type without updating all call sites; passing nil after a failed SendPreviewStart.","solutions":["Always pass the exact value returned by SendPreviewStart to UpdateMessage, unmodified","Do not construct or substitute handles manually — *previewHandle is an unexported, platform-specific type","If storing handles, keep them per-platform and keyed as the engine returns them","Check the %T value in the error to identify which wrong type is being passed"],"exampleFix":"// before\nhandle := rctx // wrong: reply context, not the preview handle\nerr := p.UpdateMessage(ctx, handle, text)\n// after\nhandle, err := p.SendPreviewStart(ctx, rctx, initialText)\nif err != nil { return err }\nerr = p.UpdateMessage(ctx, handle, text)","handlingStrategy":"type-guard","validationCode":"// caller-side pre-check\nif _, ok := handle.(*googlechat.Platform) == false && handle == nil {\n    // only pass the exact value returned by SendPreviewStart\n}","typeGuard":"func isPreviewHandle(handle any) bool {\n    _, ok := handle.(interface{ matches(*previewHandle) bool })\n    return ok // or, within package: _, ok := handle.(*previewHandle); return ok\n}","tryCatchPattern":"if err := p.UpdateMessage(ctx, handle, text); err != nil {\n    if strings.Contains(err.Error(), \"invalid preview handle type\") {\n        return fmt.Errorf(\"UpdateMessage requires the value returned by SendPreviewStart, got %v\", err)\n    }\n    return err\n}","preventionTips":["Thread the SendPreviewStart return value through your code unchanged","Never cache reply contexts as handles; keep the two concepts separate","Never share handles across platform adapters","Check for SendPreviewStart errors before calling UpdateMessage so nil handles are never propagated"],"tags":["googlechat","type-assertion","handle","streaming-preview"],"backgroundTag":"type-mismatch","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}