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
- Re-call the disconnect endpoint with ?force=true to force removal.
- Remove the connection from all agents referencing it (inspect agents' tool/provider configs), then retry without force.
- 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
- Check usage via the usage endpoint before disconnecting.
- Detatch connections from agents as part of offboarding cleanup.
- Treat 409 as an expected signal, not a crash.
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
- Skill with id "${id}" already exists.
- DATASET_ITEM_IDENTITY_CONFLICT
- Agent with id ${id} already exists
- MCP client with id ${id} already exists
- Scorer definition with id ${id} already exists
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/5c9020e34cf87eec.
Report an issue: GitHub.