{"record":{"id":"7b206bbefc21c9cf","repo":"mastra-ai/mastra","slug":"no-adapter-for-platform-platform","errorCode":null,"errorMessage":"No adapter for platform \"${platform}\"","messagePattern":"No adapter for platform \"(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/channels/agent-channels.ts","lineNumber":534,"sourceCode":"        if (!actionId.startsWith('tool_approve:') && !actionId.startsWith('tool_deny:')) return;\n        try {\n          const approved = actionId.startsWith('tool_approve:');\n          const toolCallId = actionId.split(':')[1];\n          if (!toolCallId) {\n            this.log('info', `Missing toolCallId in action event actionId=${actionId}`);\n            return;\n          }\n\n          const chatThread = event.thread as Thread | null;\n          if (!chatThread) {\n            this.log('info', `No thread in action event for toolCallId=${toolCallId}`);\n            return;\n          }\n          const platform = event.adapter.name;\n          const messageId = event.messageId;\n          const adapter = this.adapters[platform];\n          const adapterConfig = this.adapterConfigs[platform];\n          if (!adapter) throw new Error(`No adapter for platform \"${platform}\"`);\n\n          const externalThreadId = this.resolveExternalThreadId({ platform, chatThread, messageId });\n          const { thread: mastraThread } = await this.findThreadMapping({\n            externalThreadId,\n            channelId: chatThread.channelId,\n            platform,\n            mastra,\n          });\n          if (!mastraThread) {\n            // Approval cards can only continue runs on threads created by an\n            // earlier message. Do not mint a replacement from the clicker's\n            // identity when that durable mapping is missing.\n            this.log('warn', `No mapped channel thread found for tool approval action toolCallId=${toolCallId}`);\n            return;\n          }\n\n          // Look up the runId for this toolCallId. Prefer the in-memory\n          // `pendingApprovalCards` map (set when the approval card was posted)","sourceCodeStart":516,"sourceCodeEnd":552,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/channels/agent-channels.ts#L516-L552","documentation":"When AgentChannels processes an incoming platform event, it looks up the registered adapter by the event adapter's platform name. If the event's platform has no matching entry in this.adapters, it throws, because messages from that platform cannot be handled.","triggerScenarios":"A channel event arrives (e.g. via inbound webhook dispatch) whose adapter.name is not among the adapters registered on the AgentChannels instance — e.g. the event was routed to the wrong channels instance, or the adapter was registered under a different name/platform key.","commonSituations":"Registering an adapter with `adapters: { slack: slackAdapter }` but events arrive labeled 'slack-rtm' or 'teams'; multiple channel deployments sharing one webhook URL; renaming a platform key without redeploying the sender side.","solutions":["Register an adapter for that platform key in the AgentChannels `adapters` config","Ensure the adapter's `name` property matches the key it is registered under","Check webhook routing so events only reach the channels instance that registered the matching adapter"],"exampleFix":"// before\nnew AgentChannels({ adapters: { slack: slackAdapter } }); // event from 'teams' throws\n// after\nnew AgentChannels({ adapters: { slack: slackAdapter, teams: teamsAdapter } });","handlingStrategy":"validation","validationCode":"const platform = event.adapter.name;\nif (!(platform in channels.adapters)) {\n  console.warn(`Dropping event from unregistered platform: ${platform}`);\n  return;\n}","typeGuard":"function isRegisteredAdapter(p: string, adapters: Record<string, unknown>): p is keyof typeof adapters {\n  return p in adapters;\n}","tryCatchPattern":"try {\n  await handleChannelEvent(event);\n} catch (err) {\n  if (err instanceof Error && /^No adapter for platform/.test(err.message)) {\n    logger.warn({ platform: event.adapter.name }, 'event dropped: no adapter');\n  } else throw err;\n}","preventionTips":["Keep adapter registration keys identical to each adapter's `name`","Centralize the platform-name constant shared by sender and receiver","Test each registered adapter end-to-end with a sample event"],"tags":["channels","adapter","configuration"],"backgroundTag":"missing-adapter-registration","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}