mastra-ai/mastra · warning · HTTPException

Connection ${connectionId} is still pinned by ${usage} agent

Error message

Connection ${connectionId} is still pinned by ${usage} agent(s). Pass ?force=true to disconnect anyway.

What it means

Thrown when a DELETE request to disconnect a tool provider connection is made without `?force=true` while the connection is still referenced by one or more agents. The server counts references via countConnectionUsage and refuses to silently break agents that depend on the connection. This is an intentional safety guard (HTTP 409) against orphaning agent tool configs.

Source

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

      // against another tenant's connectionId by guessing it.
      if (store && !matched && !isAdmin) {
        throw new HTTPException(403, {
          message: 'You do not have permission to disconnect this connection',
        });
      }

      const effectiveOwner = ownerAuthorId ?? callerAuthorId;
      const isShared = ownerScope === 'shared';
      if (!isShared && effectiveOwner !== callerAuthorId && !isAdmin) {
        throw new HTTPException(403, {
          message: 'You do not have permission to disconnect this connection',
        });
      }

      if (!isForce) {
        const usage = await countConnectionUsage(mastra, connectionId);
        if (usage > 0) {
          throw new HTTPException(409, {
            message: `Connection ${connectionId} is still pinned by ${usage} agent(s). Pass ?force=true to disconnect anyway.`,
          });
        }
      }

      let revoked = false;
      if (provider.capabilities?.supportsRevoke && typeof provider.revokeConnection === 'function') {
        await provider.revokeConnection(connectionId);
        revoked = true;
      }

      if (store) {
        await store.deleteConnection({
          authorId: effectiveOwner,
          providerId: provider.info.id,
          connectionId,
        });
      }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-call the disconnect endpoint with ?force=true to force removal.
  2. Remove the connection from all agents referencing it (inspect agents' tool/provider configs), then retry without force.
  3. Use the connection usage endpoint to list the pinning agents before deciding.

Example fix

// before
await fetch(`/api/tool-providers/${providerId}/connections/${connectionId}`, { method: 'DELETE' });
// after
await fetch(`/api/tool-providers/${providerId}/connections/${connectionId}?force=true`, { method: 'DELETE' });
Defensive patterns

Strategy: try-catch

Validate before calling

const usage = await api.get(`/api/tool-providers/${providerId}/connections/${connectionId}/usage`);
const isPinned = usage.agents.length > 0;
if (isPinned && !confirmForce) throw new Error(`Connection still used by ${usage.agents.length} agent(s)`);

Try / catch

try {
  await api.delete(`/api/tool-providers/${p}/connections/${id}`);
} catch (e) {
  if (e.status === 409) await api.delete(`/api/tool-providers/${p}/connections/${id}?force=true`);
  else throw e;
}

Prevention

When it happens

Trigger: DELETE /api/tool-providers/:providerId/connections/:connectionId without the force query parameter, while countConnectionUsage(mastra, connectionId) returns > 0 agents referencing that connection.

Common situations: Disconnecting an OAuth/provider connection that is still attached to agents via toolsResolver; cleanup scripts removing connections in shared environments; stale connections still wired into agent definitions after a migration.

Related errors


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