{"record":{"id":"2eb158a02dba6b4a","repo":"chenhg5/cc-connect","slug":"platform-q-does-not-support-proactive-messaging-2eb158","errorCode":null,"errorMessage":"platform %q does not support proactive messaging","messagePattern":"platform %q does not support proactive messaging","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/engine.go","lineNumber":11420,"sourceCode":"\t\t\tif candidate.Name() == platformName {\n\t\t\t\ttargetPlatform = candidate\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif targetPlatform == nil {\n\t\t\tfor _, candidate := range e.platforms {\n\t\t\t\tneedle := \":\" + candidate.Name() + \":\"\n\t\t\t\tif idx := strings.Index(strippedKey, needle); idx >= 0 {\n\t\t\t\t\ttargetPlatform = candidate\n\t\t\t\t\tstrippedKey = strippedKey[idx+1:]\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif targetPlatform != nil {\n\t\t\trc, ok := targetPlatform.(ReplyContextReconstructor)\n\t\t\tif !ok {\n\t\t\t\treturn sendTarget{}, fmt.Errorf(\"platform %q does not support proactive messaging\", targetPlatform.Name())\n\t\t\t}\n\t\t\treconstructed, err := rc.ReconstructReplyCtx(strippedKey)\n\t\t\tif err != nil {\n\t\t\t\treturn sendTarget{}, fmt.Errorf(\"reconstruct reply context: %w\", err)\n\t\t\t}\n\t\t\tp = targetPlatform\n\t\t\treplyCtx = reconstructed\n\t\t\tresolvedSessionKey = strippedKey\n\t\t}\n\t}\n\n\treturn sendTarget{\n\t\tstate:      state,\n\t\tplatform:   p,\n\t\treplyCtx:   replyCtx,\n\t\tsessionKey: resolvedSessionKey,\n\t}, nil\n}","sourceCodeStart":11402,"sourceCodeEnd":11438,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/engine.go#L11402-L11438","documentation":"For proactive sends (session key with no live interactive state), the engine falls back to reconstructing reply context from the session key. If the resolved target platform does not implement the optional ReplyContextReconstructor interface, proactive messaging is impossible on that platform and this error is returned.","triggerScenarios":"Sending to a stripped session key whose platform is resolved via registry lookup, where the platform adapter lacks ReconstructReplyCtx — e.g. a minimal or older adapter.","commonSituations":"Timer/cron-driven outbound messages to platforms without proactive support; adapters that only reply within existing event-driven conversations; platform swapped in config to one without the capability.","solutions":["Use a platform that implements ReplyContextReconstructor for proactive messaging","Implement ReconstructReplyCtx on the platform adapter (persist reply context at message-receive time)","Change the flow to reply inside an existing session instead of initiating proactively"],"exampleFix":"// before\nfunc (p *Platform) Name() string { return \"mini\" } // no ReconstructReplyCtx\n// after\nfunc (p *Platform) ReconstructReplyCtx(key string) (any, error) {\n    return p.loadReplyCtx(key)\n}","handlingStrategy":"type-guard","validationCode":"if _, ok := platform.(core.ReplyContextReconstructor); !ok {\n    return fmt.Errorf(\"proactive messaging unavailable on %s\", platform.Name())\n}","typeGuard":"func supportsProactive(p core.Platform) bool { _, ok := p.(core.ReplyContextReconstructor); return ok }","tryCatchPattern":"if err := engine.SendToSession(...); err != nil {\n    if errors.Is(err, core.ErrNotSupported) { log.Warn(\"platform cannot message proactively; scheduling inside session instead\") }\n}","preventionTips":["Check ReplyContextReconstructor support before designing proactive flows","Implement the interface on adapters that need push messaging","Prefer platforms with proactive support for cron-driven bots"],"tags":["go","capability","proactive-messaging"],"backgroundTag":"unsupported-operation","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"}