{"record":{"id":"396c412ca3b188ba","repo":"chenhg5/cc-connect","slug":"qq-sendimage-invalid-reply-context-type-t","errorCode":null,"errorMessage":"qq: SendImage: invalid reply context type %T","messagePattern":"qq: SendImage: invalid reply context type %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/qq/qq.go","lineNumber":472,"sourceCode":"\t}\n\n\tif rctx.messageType == \"group\" {\n\t\tparams[\"group_id\"] = rctx.groupID\n\t\t_, err := p.callAPI(\"send_group_msg\", params)\n\t\treturn err\n\t}\n\n\tparams[\"user_id\"] = rctx.userID\n\t_, err := p.callAPI(\"send_private_msg\", params)\n\treturn err\n}\n\n// SendImage sends an image to the conversation.\n// Implements core.ImageSender.\nfunc (p *Platform) SendImage(ctx context.Context, replyCtx any, img core.ImageAttachment) error {\n\trctx, ok := replyCtx.(*replyContext)\n\tif !ok {\n\t\treturn fmt.Errorf(\"qq: SendImage: invalid reply context type %T\", replyCtx)\n\t}\n\n\tb64 := base64.StdEncoding.EncodeToString(img.Data)\n\tsegments := []map[string]any{\n\t\t{\"type\": \"image\", \"data\": map[string]any{\"file\": \"base64://\" + b64}},\n\t}\n\n\tparams := map[string]any{\n\t\t\"message\": segments,\n\t}\n\n\tif rctx.messageType == \"group\" {\n\t\tparams[\"group_id\"] = rctx.groupID\n\t\t_, err := p.callAPI(\"send_group_msg\", params)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"qq: send image: %w\", err)\n\t\t}\n\t\treturn nil","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/qq/qq.go#L454-L490","documentation":"Returned by Platform.SendImage (the core.ImageSender implementation) when replyCtx is not a *replyContext. Same contract as Send: the image sender only accepts the internal reply context pointer produced for a previously received QQ message, and reports the offending type (%T) to ease diagnosis.","triggerScenarios":"Calling SendImage(ctx, replyCtx, img) with nil, a string/int conversation ID, a map-based context, a value-type replyContext, or a context from another platform.","commonSituations":"Forwarding a reply context received from Telegram/Feishu into the QQ adapter; decoding a stored JSON blob back into map[string]any and passing it; passing the core.Message object itself instead of its reply context field.","solutions":["Pass the original *replyContext delivered with the inbound QQ message.","Check the %T in the message: it names the actual type you passed — correct it to the platform's reply context pointer type.","If routing across platforms, re-derive the context from a message received by the qq Platform, not a foreign one.","Guard with a type assertion before calling SendImage if the context comes from untyped storage."],"exampleFix":"// before\nplatform.SendImage(ctx, map[string]any{\"group_id\": 123}, img)\n\n// after\nplatform.SendImage(ctx, replyCtx, img) // replyCtx from inbound message events","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func validImageTarget(replyCtx any) bool {\n    _, ok := replyCtx.(*replyContext)\n    return ok\n}","tryCatchPattern":"if err := p.SendImage(ctx, replyCtx, img); err != nil {\n    if strings.Contains(err.Error(), \"invalid reply context type\") {\n        slog.Error(\"SendImage got non-qq context\", \"type\", fmt.Sprintf(\"%T\", replyCtx))\n    }\n    return err\n}","preventionTips":["Store and pass the reply context pointer as received from message events","Tag contexts with their platform to catch cross-platform mix-ups","Add unit tests asserting SendImage rejects foreign context types","Avoid converting contexts through JSON or maps"],"tags":["type-assertion","image","api-misuse","qq"],"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"}