{"record":{"id":"aa9d86c7349643f3","repo":"mastra-ai/mastra","slug":"no-channel-context-cannot-determine-platform-or","errorCode":null,"errorMessage":"No channel context — cannot determine platform or thread","messagePattern":"No channel context — cannot determine platform or thread","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/channels/agent-channels.ts","lineNumber":944,"sourceCode":"   * Replies don't need a tool: the agent's response streams back to the\n   * channel through the output processor.\n   */\n  getTools(): Record<string, unknown> {\n    if (!this.toolsEnabled) return {};\n    return this.makeChannelTools();\n  }\n\n  // ---------------------------------------------------------------------------\n  // Private\n  // ---------------------------------------------------------------------------\n\n  /**\n   * Resolve the adapter for the current conversation from request context.\n   */\n  private getAdapterFromContext(context: { requestContext?: RequestContext }): { adapter: Adapter; threadId: string } {\n    const channel = context.requestContext?.get('channel') as ChannelContext | undefined;\n    if (!channel?.platform || !channel?.threadId) {\n      throw new Error('No channel context — cannot determine platform or thread');\n    }\n    const adapter = this.adapters[channel.platform];\n    if (!adapter) {\n      throw new Error(`No adapter registered for platform \"${channel.platform}\"`);\n    }\n    return { adapter, threadId: channel.threadId };\n  }\n\n  /**\n   * Derive the three per-event shapes we hand off to downstream systems from one set of\n   * inputs. Keeping this in one place ensures the LLM (`attributes`), input processors\n   * (`requestContext`), and memory (`metadata`) all see consistent author / thread facts.\n   *\n   *   - `channelContext` — goes on `requestContext` under the 'channel' key, consumed by\n   *     `ChatChannelProcessor` and other input processors.\n   *   - `attributes` — serialized as XML on the user message element the LLM sees (e.g. on\n   *     `<user messageId=... authorId=... />`). Strings only.\n   *   - `providerOptions` — written to the stored message's `content.providerMetadata`","sourceCodeStart":926,"sourceCodeEnd":962,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/channels/agent-channels.ts#L926-L962","documentation":"getAdapterFromContext resolves the current platform/thread from RequestContext key 'channel'. If the request context contains no channel entry (or it lacks platform/threadId), the method cannot determine which adapter or thread to use and throws.","triggerScenarios":"Calling a channel-scoped API (e.g. reply or thread resolution via context) on a request that did not originate through a channel — the 'channel' RequestContext key was never set, or the ChannelContext object is missing platform/threadId fields.","commonSituations":"Invoking the same agent endpoint directly (HTTP/Playground) instead of through a channel integration; forgetting to forward request context through a middleware or sub-call; building a custom integration that neglects to set the 'channel' key.","solutions":["Only call channel-context-dependent APIs for requests that came through a channel; branch on the presence of context first","Set the 'channel' key in RequestContext ({ platform, threadId }) before invoking, e.g. in your webhook handler","If invoking programmatically, pass a requestContext with a well-formed ChannelContext"],"exampleFix":"// before\nawait channels.reply('hello', { requestContext: ctx }); // ctx has no 'channel'\n// after\nctx.set('channel', { platform: 'slack', threadId: 'C123' });\nawait channels.reply('hello', { requestContext: ctx });","handlingStrategy":"validation","validationCode":"const channel = ctx?.get('channel') as ChannelContext | undefined;\nif (!channel?.platform || !channel?.threadId) {\n  return fallbackNonChannelHandler();\n}\nawait channels.reply(message, { requestContext: ctx });","typeGuard":"function isChannelContext(v: unknown): v is { platform: string; threadId: string } {\n  const c = v as any;\n  return !!c && typeof c.platform === 'string' && typeof c.threadId === 'string';\n}","tryCatchPattern":"try {\n  await channels.reply(message, { requestContext: ctx });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('No channel context')) {\n    logger.warn('Request did not originate from a channel; skipping channel reply');\n  } else throw err;\n}","preventionTips":["Branch on channel-context presence before channel-only APIs","Always set the 'channel' RequestContext key in your webhook/integration layer","Propagate requestContext through middleware and sub-calls"],"tags":["channels","request-context","missing-context"],"backgroundTag":"missing-request-context","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}