{"record":{"id":"db9f49dba44e504f","repo":"chenhg5/cc-connect","slug":"platform-q-does-not-support-proactive-messaging","errorCode":null,"errorMessage":"platform %q does not support proactive messaging (cron)","messagePattern":"platform %q does not support proactive messaging \\(cron\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/engine.go","lineNumber":1503,"sourceCode":"\t// Search for a known platform name within the key and strip the prefix.\n\tif targetPlatform == nil {\n\t\tfor _, p := range e.platforms {\n\t\t\tneedle := \":\" + p.Name() + \":\"\n\t\t\tif idx := strings.Index(sessionKey, needle); idx >= 0 {\n\t\t\t\ttargetPlatform = p\n\t\t\t\tplatformName = p.Name()\n\t\t\t\tsessionKey = sessionKey[idx+1:] // strip workspace prefix\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\tif targetPlatform == nil {\n\t\treturn fmt.Errorf(\"platform %q not found for session %q\", platformName, sessionKey)\n\t}\n\n\trc, ok := targetPlatform.(ReplyContextReconstructor)\n\tif !ok {\n\t\treturn fmt.Errorf(\"platform %q does not support proactive messaging (cron)\", platformName)\n\t}\n\n\trunSessionKey := sessionKey\n\tvar replyCtx any\n\tvar err error\n\tif !job.Mute {\n\t\tif resolver, ok := targetPlatform.(CronReplyTargetResolver); ok {\n\t\t\tresolvedSessionKey, resolvedReplyCtx, err := resolver.ResolveCronReplyTarget(sessionKey, cronRunTitle(job))\n\t\t\tif err != nil {\n\t\t\t\tif !errors.Is(err, ErrNotSupported) {\n\t\t\t\t\treturn fmt.Errorf(\"resolve cron reply target: %w\", err)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif resolvedSessionKey != \"\" {\n\t\t\t\t\trunSessionKey = resolvedSessionKey\n\t\t\t\t}\n\t\t\t\tif resolvedReplyCtx != nil {\n\t\t\t\t\treplyCtx = resolvedReplyCtx","sourceCodeStart":1485,"sourceCodeEnd":1521,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/engine.go#L1485-L1521","documentation":"After locating the target platform for a cron job, ExecuteCronJob requires it to implement the optional ReplyContextReconstructor interface so it can build a reply context for proactive messaging. If the platform adapter does not implement it, the engine returns 'platform %q does not support proactive messaging (cron)'. This is a capability gap in the platform adapter, not a runtime failure — some simpler platform adapters simply cannot initiate messages to a reconstructed context.","triggerScenarios":"A cron job's SessionKey resolves to a platform registered in e.platforms that compiles and runs but does not implement ReplyContextReconstructor (the type assertion targetPlatform.(ReplyContextReconstructor) fails), and a cron job is scheduled against it.","commonSituations":"Scheduling a cron job on a minimal/custom platform adapter that only supports replying within an active conversation; using a platform integration that never implemented proactive message support; running a stripped build where the full-capability adapter was replaced.","solutions":["Move the cron job to a platform adapter that implements ReplyContextReconstructor (e.g. feishu, telegram, slack).","If you own the adapter, implement ReplyContextReconstructor.ReconstructReplyCtx(sessionKey) so proactive cron messaging works.","Disable cron jobs for that platform (remove the scheduled jobs referencing it) to avoid the error at every trigger.","Check whether a fuller implementation of the platform exists in this repo before writing a custom one."],"exampleFix":"// before: adapter without proactive support\nfunc (p *Platform) Name() string { return \"miniplat\" }\n// after: add the required capability\nfunc (p *Platform) ReconstructReplyCtx(sessionKey string) (any, error) {\n    chatID, ok := parseChatID(sessionKey)\n    if !ok {\n        return nil, fmt.Errorf(\"miniplat: invalid session key %q\", sessionKey)\n    }\n    return &ReplyCtx{ChatID: chatID}, nil\n}","handlingStrategy":"type-guard","validationCode":"// Go: check capability before scheduling a cron job on a platform\nif _, ok := platform.(core.ReplyContextReconstructor); !ok {\n    return fmt.Errorf(\"platform %s cannot host cron jobs (no proactive messaging)\", platform.Name())\n}","typeGuard":"rc, ok := targetPlatform.(core.ReplyContextReconstructor); if !ok { /* platform cannot do proactive cron messaging */ }","tryCatchPattern":"if err := engine.ExecuteCronJob(job); err != nil {\n    if strings.Contains(err.Error(), \"does not support proactive messaging\") {\n        slog.Warn(\"disabling cron on non-proactive platform\", \"job\", job.ID, \"err\", err)\n        scheduler.Disable(job.ID)\n    }\n}","preventionTips":["Only schedule cron jobs on platforms known to implement ReplyContextReconstructor.","When writing a custom platform adapter, implement ReplyContextReconstructor if cron support is desired.","Run a capability check at cron-registration time, not just at trigger time.","Prefer bundled full-featured adapters over minimal custom ones for scheduled messaging."],"tags":["cron","capability-interface","platform-adapter","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-14T00:17:10.932Z"}