{"record":{"id":"6608081bec5e1b4f","repo":"chenhg5/cc-connect","slug":"operation-not-supported-by-this-platform","errorCode":null,"errorMessage":"operation not supported by this platform","messagePattern":"operation not supported by this platform","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/interfaces.go","lineNumber":48,"sourceCode":"\t\t}\n\t}\n\tif v, ok := m[LangEnglish]; ok && v != \"\" {\n\t\treturn v\n\t}\n\treturn string(key)\n}\n\n// Platform abstracts a messaging platform (Feishu, DingTalk, Slack, etc.).\ntype Platform interface {\n\tName() string\n\tStart(handler MessageHandler) error\n\tReply(ctx context.Context, replyCtx any, content string) error\n\tSend(ctx context.Context, replyCtx any, content string) error\n\tStop() error\n}\n\n// ErrNotSupported indicates a platform doesn't support a particular operation.\nvar ErrNotSupported = errors.New(\"operation not supported by this platform\")\n\n// ReplyContextReconstructor is an optional interface for platforms that can\n// recreate a reply context from a session key. This is needed for cron jobs\n// to send messages to users without an incoming message.\ntype ReplyContextReconstructor interface {\n\tReconstructReplyCtx(sessionKey string) (any, error)\n}\n\n// RelayGroupVisibilityTarget is an optional interface for platforms that\n// want to customise the session key used when echoing relay request /\n// response messages into the group chat for visibility.  Platforms that\n// understand the concept of a thread, topic, or sub-conversation can\n// return a thread-scoped session key so the visibility echoes land in\n// the same conversation that triggered the relay; platforms without\n// such a concept simply don't implement this interface and core falls\n// back to the legacy \"<platform>:<chatID>:relay\" target.\n//\n// Returning (key, true) → core uses key verbatim as the group session","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/interfaces.go#L30-L66","documentation":"ErrNotSupported is the core sentinel meaning the connected platform adapter cannot perform the requested operation. Callers check optional capability maps (e.g. capabilities[\"update_message\"], capabilities[\"preview\"]) and return this error when the adapter is missing or lacks the capability. It lets generic core code degrade gracefully across heterogeneous platforms.","triggerScenarios":"Calling bridge paths that edit or preview messages (core/bridge.go:515, core/bridge.go:532) when getAdapter(platform) returns nil or the adapter's capabilities map lacks the required key (e.g. update_message, preview).","commonSituations":"Invoking /edit or message preview on a platform (QQ, LINE, etc.) whose adapter did not declare update_message/preview capability; a stale session referencing a platform adapter that was never registered; cron/delayed reply paths hitting a platform that only supports plain Send.","solutions":["Check support before calling: verify the platform adapter exposes the capability (capabilities map or optional interface) and skip/hide the feature otherwise.","Handle the sentinel with errors.Is(err, core.ErrNotSupported) and disable the corresponding UI affordance for that platform.","Implement the operation in the platform adapter and register it in its capabilities map if the platform truly supports it."],"exampleFix":"// before\nif err := bridge.UpdateMessage(ctx, rc, newContent); err != nil {\n    return err\n}\n// after\nif err := bridge.UpdateMessage(ctx, rc, newContent); err != nil {\n    if errors.Is(err, core.ErrNotSupported) {\n        return bridge.Send(ctx, rc.replyCtx, newContent) // fallback to new message\n    }\n    return err\n}","handlingStrategy":"fallback","validationCode":"adapter := getAdapter(platformName)\nsupported := adapter != nil && adapter.capabilities[\"update_message\"]","typeGuard":"func supportsUpdateMessage(p core.Platform) bool {\n    type cap interface{ Capabilities() map[string]bool }\n    c, ok := p.(cap)\n    return ok && c.Capabilities()[\"update_message\"]\n}","tryCatchPattern":"if errors.Is(err, core.ErrNotSupported) {\n    // degrade: fall back to sending a new message or hide the feature\n}","preventionTips":["Gate UI commands (edit, preview) on the platform's declared capabilities.","Keep each adapter's capabilities map in sync with what it actually implements.","Write a table-driven test asserting which operations each platform supports."],"tags":["platform","capabilities","unsupported-operation","bridge"],"backgroundTag":"operation-not-supported","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"}