{"record":{"id":"14fd44c184af0767","repo":"mastra-ai/mastra","slug":"mcp-client-unsubscribe-resource-failed","errorCode":"MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED","errorMessage":"MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED","messagePattern":"MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"warning","filePath":"packages/mcp/src/client/configuration.ts","lineNumber":449,"sourceCode":"      /**\n       * Unsubscribes from updates for a specific resource on a server.\n       *\n       * @param serverName - Name of the server\n       * @param uri - URI of the resource to unsubscribe from\n       * @returns Promise resolving when unsubscription is complete\n       * @throws {MastraError} If unsubscription fails\n       *\n       * @example\n       * ```typescript\n       * await mcp.resources.unsubscribe('weatherServer', 'file://config.json');\n       * ```\n       */\n      unsubscribe: async (serverName: string, uri: string) => {\n        try {\n          const internalClient = await this.getConnectedClientForServer(serverName);\n          return internalClient.resources.unsubscribe(uri);\n        } catch (err) {\n          throw new MastraError(\n            {\n              id: 'MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED',\n              domain: ErrorDomain.MCP,\n              category: ErrorCategory.THIRD_PARTY,\n              details: {\n                serverName,\n                uri,\n              },\n            },\n            err,\n          );\n        }\n      },\n      /**\n       * Sets a notification handler for when subscribed resources are updated on a server.\n       *\n       * @param serverName - Name of the server to monitor\n       * @param handler - Callback function receiving the updated resource URI","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp/src/client/configuration.ts#L431-L467","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Only call unsubscribe for URIs you successfully subscribed to (track active subscriptions in your app) and pass the exact same URI string.","Guard cleanup paths so a missing/duplicate unsubscribe doesn't crash teardown — wrap in try/catch and log.","Verify the server is still connected; if it already terminated, no unsubscribe is needed — skip it.","Confirm serverName matches the servers config."],"exampleFix":"// before\nconst subs = new Set();\nawait mcp.resources.subscribe('logs', uri); subs.add(uri);\nawait mcp.resources.unsubscribe('logs', uri); await mcp.resources.unsubscribe('logs', uri); // second call throws\n// after\nfor (const u of subs) { try { await mcp.resources.unsubscribe('logs', u); } catch {} } subs.clear();","handlingStrategy":"try-catch","validationCode":"// Only unsubscribe URIs you actually subscribed to, tracked locally\nif (!activeSubs.has(uri)) return; // nothing to unsubscribe\nawait mcp.resources.unsubscribe(serverName, uri);","typeGuard":"function isUnsubscribeError(e: unknown): e is MastraError {\n  return e instanceof MastraError && e.id === 'MCP_CLIENT_UNSUBSCRIBE_RESOURCE_FAILED';\n}","tryCatchPattern":"try {\n  await mcp.resources.unsubscribe(serverName, uri);\n} catch (e) {\n  if (isUnsubscribeError(e)) {\n    logger.debug(`no active subscription to remove for ${uri} (already gone)`, e); // safe during teardown\n  } else throw e;\n} finally {\n  activeSubs.delete(uri);\n}","preventionTips":["Track successful subscriptions in a Set and only unsubscribe those.","Pass the exact same URI string used at subscribe time.","Skip unsubscribe if the server process has already terminated.","Always wrap unsubscribe in try/catch in cleanup/shutdown paths — it must never break teardown."],"tags":["mcp","resources","unsubscribe","cleanup"],"backgroundTag":"unsupported-mcp-capability","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}