{"record":{"id":"98a156bb6dec188a","repo":"chenhg5/cc-connect","slug":"line-invalid-reply-context-type-t","errorCode":null,"errorMessage":"line: invalid reply context type %T","messagePattern":"line: invalid reply context type %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/line/line.go","lineNumber":257,"sourceCode":"\t}\n}\n\nfunc (p *Platform) downloadContent(messageID string) ([]byte, error) {\n\turl := fmt.Sprintf(\"https://api-data.line.me/v2/bot/message/%s/content\", messageID)\n\treq, _ := http.NewRequest(\"GET\", url, nil)\n\treq.Header.Set(\"Authorization\", \"Bearer \"+p.channelToken)\n\tresp, err := core.HTTPClient.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\treturn io.ReadAll(resp.Body)\n}\n\nfunc (p *Platform) Reply(ctx context.Context, rctx any, content string) error {\n\trc, ok := rctx.(replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"line: invalid reply context type %T\", rctx)\n\t}\n\n\tif content == \"\" {\n\t\treturn nil\n\t}\n\n\tcontent = core.StripMarkdown(content)\n\n\t// LINE text message limit is 5000 characters\n\tmessages := splitMessage(content, 5000)\n\tfor _, text := range messages {\n\t\t_, err := p.bot.PushMessage(\n\t\t\t&messaging_api.PushMessageRequest{\n\t\t\t\tTo: rc.targetID,\n\t\t\t\tMessages: []messaging_api.MessageInterface{\n\t\t\t\t\tmessaging_api.TextMessage{\n\t\t\t\t\t\tText: text,\n\t\t\t\t\t},","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/line/line.go#L239-L275","documentation":"Platform.Reply expects the reply context passed by the engine to be the platform-internal replyContext type; if the assertion rctx.(replyContext) fails, this error reports the actual dynamic type. This is a defensive check against callers supplying a reply context that did not originate from this LINE platform instance (e.g. from a different platform adapter or a stale/custom value).","triggerScenarios":"Calling Reply with a context value produced by another platform's adapter, a hand-constructed value of a different type, or a replyContext captured from a different line.Platform instance/older version whose struct layout differs.","commonSituations":"Mixing reply contexts across platforms when routing messages through multiple adapters; custom engine code caching reply contexts of the wrong concrete type; tests passing a stub instead of the platform's replyContext.","solutions":["Only pass reply contexts obtained from this LINE platform's incoming webhook events to Reply.","Fix routing logic that stores/shares reply contexts across different platform adapters.","In tests, construct the platform's own replyContext type rather than an arbitrary stub.","If bridging platforms, convert the foreign context into a LINE reply token before calling Reply."],"exampleFix":"// before\np.Reply(ctx, someOtherPlatformCtx, \"hello\")\n// after\nrc := line.NewReplyContext(replyTokenFromWebhookEvent)\np.Reply(ctx, rc, \"hello\")","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Go: check the reply context type before use\nif rc, ok := rctx.(line.ReplyContext); !ok {\n    return fmt.Errorf(\"not a line reply context: %T\", rctx)\n} else if rc.ReplyToken == \"\" {\n    return errors.New(\"line: empty reply token\")\n}","tryCatchPattern":"// Go: caller-side handling\nif err := platform.Reply(ctx, rctx, content); err != nil {\n    if strings.Contains(err.Error(), \"invalid reply context type\") {\n        slog.Error(\"reply context came from a different platform; dropping reply\", \"type\", fmt.Sprintf(\"%T\", rctx))\n        return nil\n    }\n    return err\n}","preventionTips":["Store reply contexts per-platform; never share them across adapters.","Type-assert reply contexts in the routing layer before dispatching to Reply.","Keep replyContext definitions stable across versions when caching contexts.","Write tests that exercise Reply with the platform's own context type."],"tags":["line","type-assertion","api-misuse"],"backgroundTag":"invalid-argument-value","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"}