mastra-ai/mastra · error
No channel context — cannot determine platform or thread
Error message
No channel context — cannot determine platform or thread
What it means
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.
Source
Thrown at packages/core/src/channels/agent-channels.ts:944
* Replies don't need a tool: the agent's response streams back to the
* channel through the output processor.
*/
getTools(): Record<string, unknown> {
if (!this.toolsEnabled) return {};
return this.makeChannelTools();
}
// ---------------------------------------------------------------------------
// Private
// ---------------------------------------------------------------------------
/**
* Resolve the adapter for the current conversation from request context.
*/
private getAdapterFromContext(context: { requestContext?: RequestContext }): { adapter: Adapter; threadId: string } {
const channel = context.requestContext?.get('channel') as ChannelContext | undefined;
if (!channel?.platform || !channel?.threadId) {
throw new Error('No channel context — cannot determine platform or thread');
}
const adapter = this.adapters[channel.platform];
if (!adapter) {
throw new Error(`No adapter registered for platform "${channel.platform}"`);
}
return { adapter, threadId: channel.threadId };
}
/**
* Derive the three per-event shapes we hand off to downstream systems from one set of
* inputs. Keeping this in one place ensures the LLM (`attributes`), input processors
* (`requestContext`), and memory (`metadata`) all see consistent author / thread facts.
*
* - `channelContext` — goes on `requestContext` under the 'channel' key, consumed by
* `ChatChannelProcessor` and other input processors.
* - `attributes` — serialized as XML on the user message element the LLM sees (e.g. on
* `<user messageId=... authorId=... />`). Strings only.
* - `providerOptions` — written to the stored message's `content.providerMetadata`View on GitHub (pinned to 75dd419e61)
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
Example fix
// before
await channels.reply('hello', { requestContext: ctx }); // ctx has no 'channel'
// after
ctx.set('channel', { platform: 'slack', threadId: 'C123' });
await channels.reply('hello', { requestContext: ctx }); Defensive patterns
Strategy: validation
Validate before calling
const channel = ctx?.get('channel') as ChannelContext | undefined;
if (!channel?.platform || !channel?.threadId) {
return fallbackNonChannelHandler();
}
await channels.reply(message, { requestContext: ctx }); Type guard
function isChannelContext(v: unknown): v is { platform: string; threadId: string } {
const c = v as any;
return !!c && typeof c.platform === 'string' && typeof c.threadId === 'string';
} Try / catch
try {
await channels.reply(message, { requestContext: ctx });
} catch (err) {
if (err instanceof Error && err.message.includes('No channel context')) {
logger.warn('Request did not originate from a channel; skipping channel reply');
} else throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No adapter registered for platform "${channel.platform}"
- browser_close requires agent.threadId when browser scope is
- MastraFactory: integrations [${channelRegistrations.map(({ i
- GitHub token refresh requires an active Factory sandbox work
- Factory review phase requires a controller request context.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/aa9d86c7349643f3.
Report an issue: GitHub.