mastra-ai/mastra · error · HTTPException

Tool provider ${providerId} does not support listConnections

Error message

Tool provider ${providerId} does not support listConnections

What it means

HTTP 400 thrown by the list-connections handler when the provider does not implement the optional listConnections method. Enumerating stored connections for a provider is opt-in, so providers lacking the method cannot list their connections.

Source

Thrown at packages/server/src/server/handlers/tool-providers.ts:434

  description:
    'Returns existing provider connections on a toolkit, so the picker can offer them for pinning without re-running OAuth',
  tags: ['Tool Providers'],
  requiresAuth: true,
  handler: async ({
    mastra,
    providerId,
    toolkit,
    authorId: queryAuthorId,
    scope: queryScope,
    page,
    perPage,
    requestContext,
  }) => {
    try {
      const editor = requireEditor(mastra.getEditor());
      const provider = await resolveProvider(editor, providerId);
      if (!provider.listConnections) {
        throw new HTTPException(400, { message: `Tool provider ${providerId} does not support listConnections` });
      }
      const callerAuthorId = resolveOwnerId(requestContext, mastra.getLogger());
      const isAdmin = requestContext ? hasAdminBypass(requestContext, TOOL_PROVIDERS_RESOURCE) : false;

      const requestedAuthorId =
        isAdmin && typeof queryAuthorId === 'string' && queryAuthorId.length > 0 ? queryAuthorId : undefined;
      const effectiveAuthorId = isAdmin ? requestedAuthorId : callerAuthorId;

      const storage = mastra.getStorage();
      const store = await storage?.getStore('toolProviderConnections');

      // Strategy B: seed userIds[] from persisted rows so admins can enumerate
      // connections owned by other authors.
      let labelRows: Array<{
        authorId: string;
        connectionId: string;
        label: string | null;
        scope: 'shared' | 'per-author' | 'caller-supplied';

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Implement listConnections(...) on the ToolProvider and re-register it.
  2. Hide the provider from the connections UI when it doesn't support listing.
  3. Upgrade the provider package to a version implementing listConnections.
  4. Catch the 400 and render an 'unsupported' state for that provider instead of failing the page.

Example fix

// before
for (const id of providerIds) connections[id] = await api.listConnections(id); // 400 for some
// after
const connections = Object.fromEntries(
  (await Promise.all(providerIds.map(async id => [id,
    supportsList(id) ? await api.listConnections(id).catch(() => null) : null])) as const)
);
Defensive patterns

Strategy: try-catch

Validate before calling

const provider = await api.getProvider(providerId);
if (typeof provider?.listConnections !== 'function') {
  return [];
}

Type guard

function supportsListConnections(p: ToolProvider): p is ToolProvider & Required<Pick<ToolProvider, 'listConnections'>> {
  return typeof p.listConnections === 'function';
}

Try / catch

try {
  return await api.listConnections(providerId);
} catch (e) {
  if (e.status === 400 && /does not support listConnections/.test(e.message)) return [];
  throw e;
}

Prevention

When it happens

Trigger: GET /api/tool-providers/:providerId/connections (tool-providers.ts:434) against a provider registered without listConnections.

Common situations: A connections settings page lists connections for every registered provider; custom provider implemented without the method; provider package version predates listConnections.

Related errors


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