{"record":{"id":"01fc2ee7d2a326b2","repo":"chenhg5/cc-connect","slug":"slack-invalid-preview-handle-type-t","errorCode":null,"errorMessage":"slack: invalid preview handle type %T","messagePattern":"slack: invalid preview handle type %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/slack/streaming.go","lineNumber":48,"sourceCode":"\t\tslack.MsgOptionText(core.MarkdownToSlackMrkdwn(content), false),\n\t}\n\tif rc.timestamp != \"\" {\n\t\topts = append(opts, slack.MsgOptionPostMessageParameters(slack.PostMessageParameters{ThreadTimestamp: rc.timestamp}))\n\t}\n\t_, ts, err := p.client.PostMessageContext(ctx, rc.channel, opts...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"slack: send preview: %w\", err)\n\t}\n\treturn &slackPreviewHandle{channel: rc.channel, timestamp: ts}, nil\n}\n\n// UpdateMessage edits the preview message in place. The engine passes the handle\n// returned by SendPreviewStart (not the reply context). Implements\n// core.MessageUpdater.\nfunc (p *Platform) UpdateMessage(ctx context.Context, previewHandle any, content string) error {\n\th, ok := previewHandle.(*slackPreviewHandle)\n\tif !ok {\n\t\treturn fmt.Errorf(\"slack: invalid preview handle type %T\", previewHandle)\n\t}\n\t_, _, _, err := p.client.UpdateMessageContext(ctx, h.channel, h.timestamp,\n\t\tslack.MsgOptionText(core.MarkdownToSlackMrkdwn(content), false),\n\t)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"slack: update preview: %w\", err)\n\t}\n\treturn nil\n}\n\nvar (\n\t_ core.MessageUpdater = (*Platform)(nil)\n\t_ core.PreviewStarter = (*Platform)(nil)\n)\n","sourceCodeStart":30,"sourceCodeEnd":63,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/slack/streaming.go#L30-L63","documentation":"UpdateMessage edits an existing preview message in place and expects the handle previously returned by SendPreviewStart (*slackPreviewHandle). This error fires when the handle argument has any other type (or is nil) — an engine/adapter contract violation indicating the caller did not thread the handle through correctly.","triggerScenarios":"The engine calls UpdateMessage with a handle from a different platform, a stale/nil handle, or the return value of a failed SendPreviewStart call.","commonSituations":"Platform switched mid-turn so a non-Slack handle reaches UpdateMessage; caller ignored the error from SendPreviewStart and used its nil handle; version skew between core and platform/slack.","solutions":["Only pass the value returned by SendPreviewStart (as *slackPreviewHandle) to UpdateMessage","Check the SendPreviewStart error before using its handle; skip UpdateMessage on failure","Recreate the session/turn so the handle is produced by the Slack adapter","Rebuild core and platform packages from the same commit to eliminate type skew"],"exampleFix":"// before\nhandle, _ := p.SendPreviewStart(ctx, rc, content) // error ignored\np.UpdateMessage(ctx, handle, more) // handle may be nil\n// after\nhandle, err := p.SendPreviewStart(ctx, rc, content)\nif err != nil { return err }\np.UpdateMessage(ctx, handle, more)","handlingStrategy":"type-guard","validationCode":"h, ok := previewHandle.(*slackPreviewHandle)\nif !ok { return fmt.Errorf(\"slack: invalid preview handle type %T\", previewHandle) }\nif h == nil { return errors.New(\"slack: nil preview handle\") }","typeGuard":"func asSlackPreviewHandle(v any) (*slackPreviewHandle, bool) { h, ok := v.(*slackPreviewHandle); return h, ok && h != nil }","tryCatchPattern":"if err := p.UpdateMessage(ctx, handle, content); err != nil {\n    slog.Warn(\"slack: preview update skipped\", \"err\", err)\n}","preventionTips":["Always check SendPreviewStart's error before using its handle","Thread the handle only within the same platform's turn","Never cache handles across sessions/platform switches","Compile core+platform together to avoid type skew"],"tags":["slack","type-mismatch","streaming","contract"],"backgroundTag":"type-mismatch","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"}