mastra-ai/mastra · error · MastraError

MCP_CLIENT_ON_LIST_CHANGED_RESOURCE_FAILED

MCP_CLIENT_ON_LIST_CHANGED_RESOURCE_FAILED

Error message

MCP_CLIENT_ON_LIST_CHANGED_RESOURCE_FAILED

What it means

Thrown when registering a handler for the resources/list_changed notification fails: MCPClient's resources.onListChanged(serverName, handler) connects and attaches the handler on the internal client; failures are wrapped in a MastraError with id MCP_CLIENT_ON_LIST_CHANGED_RESOURCE_FAILED (category THIRD_PARTY). This notification tells you when the server's set of available resources changes.

Solutions

  1. Verify serverName matches the servers configuration key exactly.
  2. Get the server connected first (test the command/args manually; check env, PATH, network) then register the handler.
  3. Re-register handlers after any reconnect, since handlers live on the in-memory internal client.
  4. Catch the error and fall back to polling resources.list() when change notifications can't be installed.

Example fix

// before
await mcp.resources.onListChanged('Docs', sync); // config key is 'docs'
// after
await mcp.resources.onListChanged('docs', sync);
Defensive patterns

Strategy: try-catch

Validate before calling

const configured = Object.keys(serversConfig);
if (!configured.includes(serverName)) throw new Error(`server not configured: ${serverName}`);

Type guard

function isOnListChangedError(e: unknown): e is MastraError {
  return e instanceof MastraError && e.id === 'MCP_CLIENT_ON_LIST_CHANGED_RESOURCE_FAILED';
}

Try / catch

try {
  await mcp.resources.onListChanged(serverName, syncResourceList);
} catch (e) {
  if (isOnListChangedError(e)) {
    logger.warn(`list-changed notifications unavailable for ${e.details?.serverName}; will poll resources.list`, e);
    startListPolling(serverName);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling mcpClient.resources.onListChanged('myServer', handler) when the server name is unknown, the server cannot be connected (bad transport config, failed spawn), or the internal onListChanged registration throws.

Common situations: Server name typo; handler registered before the client ever connected to the server; server restarted or crashed so the lookup fails; npx-based server failed to download its package in a sandboxed/CI environment.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/cf9bd8f08e9120ef. Report an issue: GitHub.

Appendix: source

Thrown at packages/mcp/src/client/configuration.ts:518

       * @param serverName - Name of the server to monitor
       * @param handler - Callback function invoked when resources are added/removed
       * @returns Promise resolving when handler is registered
       * @throws {MastraError} If setting up the handler fails
       *
       * @example
       * ```typescript
       * await mcp.resources.onListChanged('weatherServer', async () => {
       *   console.log('Resource list changed, re-fetching...');
       *   const resources = await mcp.resources.list();
       * });
       * ```
       */
      onListChanged: async (serverName: string, handler: () => void) => {
        try {
          const internalClient = await this.getConnectedClientForServer(serverName);
          return internalClient.resources.onListChanged(handler);
        } catch (err) {
          throw new MastraError(
            {
              id: 'MCP_CLIENT_ON_LIST_CHANGED_RESOURCE_FAILED',
              domain: ErrorDomain.MCP,
              category: ErrorCategory.THIRD_PARTY,
              details: {
                serverName,
              },
            },
            err,
          );
        }
      },
    };
  }

  /**
   * Provides access to prompt-related operations across all configured servers.
   *

View on GitHub (pinned to 75dd419e61)