Skip to content

[BUG] Agent channels silently fail to start under mastra start #17692

@coderberry

Description

@coderberry

Describe the Bug

A code-defined agent configured with channels (per the Channels Quickstart) connects correctly under mastra dev, but silently never connects under mastra start (the built .mastra/output bundle / deployed server). No socket connects, no webhook handler becomes ready, and no error is logged — the server otherwise boots fine and serves /health.

Root cause (traced in @mastra/core@1.41.0):

  1. Mastra.addAgent() registers each agent and, for agents with channels, fires the init fire-and-forget with no error handling:

    const agentChannelsInstance = mastraAgent.getChannels();
    if (agentChannelsInstance) {
      // ...getWebhookRoutes()...
      void agentChannelsInstance.initialize(this);   // no await, no .catch
    }

    addAgent is invoked from the Mastra constructor (config.agents.forEach(... this.addAgent(...))).

  2. AgentChannels.initialize(mastra) (packages/core/src/channels/agent-channels.ts) reads storage as its very first step:

    const storage = mastra.getStorage();
    const memoryStore = storage ? await storage.getStore("memory") : undefined;
    if (!memoryStore) {
      throw new Error("Channels require storage to be configured on the Mastra instance. Configure a storage provider like LibSQLStore.");
    }

    Under the production bundle, mastra.getStorage() is empty at this point (storage isn't wired onto the instance yet when addAgent runs during construction), so it throws — before the Chat SDK instance is created.

  3. Because step 1 is void initialize(this) with no .catch, the rejection is swallowed. The server boots normally; the channel is simply dead.

mastra dev wins the timing race (storage is ready when init runs — it logs Using MastraStateAdapter… then Slack socket mode connected); the mastra start bundle loses it and logs neither.

Distinct from #15948 (the 1.29.0 startup crash where channel webhook routes collided with /api prefix validation, since fixed): that was a visible crash from route validation. This is a silent failure from storage init-ordering plus a swallowed void initialize().

Suggested fixes:

  1. Initialize agent channels after the Mastra instance has finished wiring storage (or await storage readiness inside the channel-init path) so mastra.getStorage() is populated when AgentChannels.initialize() runs.
  2. At minimum, stop swallowing the error: wrap the void agentChannelsInstance.initialize(this) in addAgent with .catch(err => logger.error(...)), mirroring the instance-level #channels init path which already uses try/catch. The silent failure is what makes this so hard to diagnose in production.

Steps To Reproduce

  1. Configure a code-defined agent with a Slack channel (socket/gateway mode, the default) plus instance storage — the documented Quickstart:

    // agents/support-agent.ts
    import { Agent } from '@mastra/core/agent'
    import { createSlackAdapter } from '@chat-adapter/slack'
    
    export const supportAgent = new Agent({
      id: 'support-agent',
      name: 'Support Agent',
      model: 'openai/gpt-5.5',
      channels: { adapters: { slack: createSlackAdapter() } },
    })
    
    // mastra/index.ts
    import { Mastra } from '@mastra/core'
    import { LibSQLStore } from '@mastra/libsql'
    
    export const mastra = new Mastra({
      agents: { supportAgent },
      storage: new LibSQLStore({ url: process.env.DATABASE_URL }),
    })
  2. Run mastra dev → logs Using MastraStateAdapter (subscriptions persist across restarts) then [chat-sdk:slack] Slack socket mode connected. ✅ Works.

  3. Run mastra build && mastra start (same env) → server boots and serves /health, but logs none of the channel/chat lines and the Slack socket never connects — and no error is printed. ❌ Broken, silently.

  4. Confirm it's getStorage() emptiness (not an uninitialized store): pre-await storage.getStore("memory") before new Mastra(...) returns a ready store, yet the channel still doesn't connect under mastra start.

Link to Minimal Reproducible Example

https://github.com/berrydev-ai/mastra-channels-prod-repro

Expected Behavior

Agent channels should initialize under mastra start (production) exactly as they do under mastra dev — the Slack socket connects (or the webhook handler becomes ready). At minimum, any failure during channel initialization should be surfaced/logged rather than silently swallowed by the un-awaited void initialize().

Environment Information

@mastra/core:        1.41.0
mastra (CLI):        1.12.2
@mastra/libsql:      1.12.1
@chat-adapter/slack: 4.29.0
Runtime:             Bun 1.3.14 / Node.js 22
Storage:             LibSQL (DATABASE_URL)
Repro command:       `mastra build && mastra start` (production) — works under `mastra dev`

Verification

  • I have searched the existing issues to make sure this is not a duplicate
  • I have included sufficient information for the team to reproduce and understand the issue

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions