{"record":{"id":"cecdd1ac7ef0dc43","repo":"mastra-ai/mastra","slug":"client-name-exists-but-is-undefined","errorCode":null,"errorMessage":"Client ${name} exists but is undefined","messagePattern":"Client (.+?) exists but is undefined","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/mcp/src/client/configuration.ts","lineNumber":1561,"sourceCode":"    }\n    return serverConfig;\n  }\n\n  private async getOrCreateClient(name: string, config: MastraMCPServerDefinition): Promise<InternalMastraMCPClient> {\n    if (this.disconnectPromise) {\n      await this.disconnectPromise;\n    }\n\n    const exists = this.mcpClientsById.has(name);\n    const existingClient = this.mcpClientsById.get(name);\n\n    this.logger.debug('Checking connected client', { name, exists });\n\n    if (exists) {\n      // This is just to satisfy Typescript since technically you could have this.mcpClientsById.set('someKey', undefined);\n      // Should never reach this point basically we always create a new MastraMCPClient instance when we add to the Map.\n      if (!existingClient) {\n        throw new Error(`Client ${name} exists but is undefined`);\n      }\n      return existingClient;\n    }\n\n    const mcpClient = new InternalMastraMCPClient({\n      name,\n      server: config,\n      timeout: config.timeout ?? this.defaultTimeout,\n      capabilities: config.capabilities,\n    });\n\n    mcpClient.__setLogger(this.logger);\n\n    this.mcpClientsById.set(name, mcpClient);\n\n    return mcpClient;\n  }\n","sourceCodeStart":1543,"sourceCodeEnd":1579,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/mcp/src/client/configuration.ts#L1543-L1579","documentation":"Defensive Error thrown in MCPClient's connected-client lookup when the clients map reports a key as existing but the stored value is undefined. The comment notes this should basically never happen since the map is always populated with InternalMastraMCPClient instances; it exists to satisfy TypeScript narrowing and to catch map corruption.","triggerScenarios":"Practically unreachable via public API; could only occur if something external mutated the internal mcpClientsById map (e.g., setting a key to undefined directly or via debugging/serialization).","commonSituations":"Custom subclassing or monkey-patching of MCPClient internals; test code inserting undefined entries; concurrent disconnect logic removing values while leaving keys.","solutions":["Audit any code that touches mcpClientsById directly and ensure only valid InternalMastraMCPClient instances are set.","Call disconnect() to properly remove the entry, then reconnect to rebuild a clean state.","Recreate the MCPClient instance if internal state is suspected to be corrupted.","Report upstream if reproducible through public API only."],"exampleFix":"// before\nclient.mcpClientsById.set('a', undefined);\n// after\nclient.mcpClientsById.set('a', new InternalMastraMCPClient({ name: 'a', serverConfig }));\n// or to remove:\nclient.mcpClientsById.delete('a');","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isClient(c: InternalMastraMCPClient | undefined): c is InternalMastraMCPClient {\n  return c instanceof InternalMastraMCPClient;\n}","tryCatchPattern":"try {\n  const c = await client.getConnectedClientForServer(name);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('exists but is undefined')) {\n    await client.disconnect({ name });\n    // recreate client / retry\n  } else throw e;\n}","preventionTips":["Never mutate mcpClientsById directly; use public connect/disconnect APIs.","Use disconnect() to remove entries rather than setting undefined.","Avoid subclassing that bypasses the client-creation path.","Recreate the MCPClient if internal map state is suspected corrupt."],"tags":["mcp","internal-state","typescript","invariant"],"backgroundTag":"undefined-client-reference","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}