chenhg5/cc-connect · error

slack: invalid reply context type %T

Error message

slack: invalid reply context type %T

What it means

SendPreviewStart implements core.PreviewStarter and expects the reply context argument to be the platform-internal replyContext struct. This error is thrown when the engine passes some other type — an internal contract violation between core and the Slack adapter. It is a defensive type assertion, not a user-input problem.

Source

Thrown at platform/slack/streaming.go:27

	"github.com/slack-go/slack"
)

// slackPreviewHandle points at the in-flight streaming-preview message so
// UpdateMessage can edit it in place via chat.update.
type slackPreviewHandle struct {
	channel   string
	timestamp string
}

// SendPreviewStart posts the initial streaming-preview message (threaded like a
// normal reply) and returns a handle for subsequent edits. Implements
// core.PreviewStarter; together with UpdateMessage it lights up the engine's
// real-time streaming preview for Slack (the engine throttles the edits, so we
// stay within chat.update rate limits).
func (p *Platform) SendPreviewStart(ctx context.Context, rctx any, content string) (any, error) {
	rc, ok := rctx.(replyContext)
	if !ok {
		return nil, fmt.Errorf("slack: invalid reply context type %T", rctx)
	}
	opts := []slack.MsgOption{
		slack.MsgOptionText(core.MarkdownToSlackMrkdwn(content), false),
	}
	if rc.timestamp != "" {
		opts = append(opts, slack.MsgOptionPostMessageParameters(slack.PostMessageParameters{ThreadTimestamp: rc.timestamp}))
	}
	_, ts, err := p.client.PostMessageContext(ctx, rc.channel, opts...)
	if err != nil {
		return nil, fmt.Errorf("slack: send preview: %w", err)
	}
	return &slackPreviewHandle{channel: rc.channel, timestamp: ts}, nil
}

// UpdateMessage edits the preview message in place. The engine passes the handle
// returned by SendPreviewStart (not the reply context). Implements
// core.MessageUpdater.
func (p *Platform) UpdateMessage(ctx context.Context, previewHandle any, content string) error {

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check which platform created the session that triggered streaming — it must be the Slack platform
  2. Recreate the session so the reply context is built by the Slack adapter
  3. Ensure core and platform/slack are built from the same source tree (no version skew)
  4. Fix test code to pass p.ReconstructReplyCtx(...) or a replyContext value, not an arbitrary type

Example fix

// before
p.SendPreviewStart(ctx, map[string]any{"channel": "C123"}, "hi") // wrong type
// after
rc, _ := p.ReconstructReplyCtx("slack:C123")
p.SendPreviewStart(ctx, rc, "hi")
Defensive patterns

Strategy: type-guard

Validate before calling

rc, ok := rctx.(replyContext)
if !ok { return fmt.Errorf("slack: invalid reply context type %T", rctx) }

Type guard

func asSlackReplyCtx(v any) (replyContext, bool) { rc, ok := v.(replyContext); return rc, ok }

Try / catch

handle, err := p.SendPreviewStart(ctx, rctx, content)
if err != nil {
    slog.Warn("slack: preview start failed", "err", err)
    return nil // degrade to non-streaming reply
}

Prevention

When it happens

Trigger: The engine calls SendPreviewStart with a reply context produced by a different platform adapter, or with a nil/legacy context value, so rctx.(replyContext) fails.

Common situations: Mixing sessions across platforms after a config change (session restored under a different platform); core/adapter version skew where the reply context type changed; tests passing the wrong fixture.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/3347024564436688. Report an issue: GitHub.