mastra-ai/mastra · warning · MastraError

MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED

MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED

Error message

MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED

What it means

Thrown when unsubscribing from resource-change notifications fails: MCPClient's resources.unsubscribe(serverName, uri) connects and calls internalClient.resources.unsubscribe(uri); any failure is wrapped in a MastraError with id MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED (category THIRD_PARTY). It usually means there was no matching subscription or the server could not be reached to remove one.

Source

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

      /**
       * Unsubscribes from updates for a specific resource on a server.
       *
       * @param serverName - Name of the server
       * @param uri - URI of the resource to unsubscribe from
       * @returns Promise resolving when unsubscription is complete
       * @throws {MastraError} If unsubscription fails
       *
       * @example
       * ```typescript
       * await mcp.resources.unsubscribe('weatherServer', 'file://config.json');
       * ```
       */
      unsubscribe: async (serverName: string, uri: string) => {
        try {
          const internalClient = await this.getConnectedClientForServer(serverName);
          return internalClient.resources.unsubscribe(uri);
        } catch (err) {
          throw new MastraError(
            {
              id: 'MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED',
              domain: ErrorDomain.MCP,
              category: ErrorCategory.THIRD_PARTY,
              details: {
                serverName,
                uri,
              },
            },
            err,
          );
        }
      },
      /**
       * Sets a notification handler for when subscribed resources are updated on a server.
       *
       * @param serverName - Name of the server to monitor
       * @param handler - Callback function receiving the updated resource URI

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Only call unsubscribe for URIs you successfully subscribed to (track active subscriptions in your app) and pass the exact same URI string.
  2. Guard cleanup paths so a missing/duplicate unsubscribe doesn't crash teardown — wrap in try/catch and log.
  3. Verify the server is still connected; if it already terminated, no unsubscribe is needed — skip it.
  4. Confirm serverName matches the servers config.

Example fix

// before
const subs = new Set();
await mcp.resources.subscribe('logs', uri); subs.add(uri);
await mcp.resources.unsubscribe('logs', uri); await mcp.resources.unsubscribe('logs', uri); // second call throws
// after
for (const u of subs) { try { await mcp.resources.unsubscribe('logs', u); } catch {} } subs.clear();
Defensive patterns

Strategy: try-catch

Validate before calling

// Only unsubscribe URIs you actually subscribed to, tracked locally
if (!activeSubs.has(uri)) return; // nothing to unsubscribe
await mcp.resources.unsubscribe(serverName, uri);

Type guard

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

Try / catch

try {
  await mcp.resources.unsubscribe(serverName, uri);
} catch (e) {
  if (isUnsubscribeError(e)) {
    logger.debug(`no active subscription to remove for ${uri} (already gone)`, e); // safe during teardown
  } else throw e;
} finally {
  activeSubs.delete(uri);
}

Prevention

When it happens

Trigger: Calling mcpClient.resources.unsubscribe('myServer', uri) when there is no active subscription for that URI, the server doesn't support the unsubscribe capability, the server name is wrong, or the server is unreachable/disconnected.

Common situations: Double-cleanup paths calling unsubscribe twice; app shutdown attempting to unsubscribe after the server already terminated; URI string differing from the one subscribed (encoding/trailing slash); server without subscribe capability never had the subscription.

Related errors


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