paperclipai/paperclip · error · VercelConnectClientError

vercel_connect_request_failed

vercel_connect_request_failed

Error message

vercel_connect_request_failed

What it means

After fetching a token from Vercel Connect, the gateway validates that the returned token's connector matches the connection's externalCredential connectorId/connectorUid. A mismatch (or any non-authorization failure inside the getToken/round-trip path) is raised as a VercelConnectClientError with code 'vercel_connect_request_failed' and status 502, then rethrown as a ToolGatewayHttpError. It means the credential resolved to the wrong (or an unusable) upstream connector.

Solutions

  1. Re-link the Vercel Connect credential so connection.externalCredential.connectorId/connectorUid match the currently installed connector.
  2. Check Vercel status/API health; if getToken is failing transiently, retry after the upstream recovers.
  3. Verify the token connector match logic: the check uses &&, so a partial mismatch (one field equal) is silently accepted — consider requiring an exact match on both.
  4. Inspect markRemoteConnectionHealth output for the connection; a 502 here marks health 'error' and the connection may need manual repair.

Example fix

// before: token from a different connector than recorded
connectorId: 'conn_old', connectorUid: 'uid_old' // connection record
// after: re-link so the record matches the installed connector
await db.update(toolConnections).set({ externalCredential: { connectorId: 'conn_new', connectorUid: 'uid_new', ... } })
Defensive patterns

Strategy: retry

Validate before calling

// before dispatch: confirm the connection's recorded connector still matches the Vercel-side install
const expected = connection.externalCredential;
if (!expected?.connectorId || !expected?.connectorUid) throw new Error('Connection missing connector identity; re-link Vercel Connect');

Type guard

function tokenMatchesConnector(token: { connector: { id: string; uid: string } }, cred: { connectorId: string; connectorUid: string }): boolean {
  return token.connector.id === cred.connectorId && token.connector.uid === cred.connectorUid;
}

Try / catch

try {
  const headers = await resolveCredentialHeaders(session, connection, grant);
} catch (e) {
  if (e instanceof ToolGatewayHttpError && e.code === 'vercel_connect_request_failed' && e.status === 502) {
    // transient upstream failure: retry with backoff; if persistent, re-link the connector
  }
  throw e;
}

Prevention

When it happens

Trigger: vercelConnect.getToken returns a token whose connector.id differs from externalCredential.connectorId AND whose connector.uid differs from externalCredential.connectorUid (note the && — matching only one field still passes); or getToken/network throws a generic error that is normalized to code 'vercel_connect_request_failed' with status 502 in the catch block.

Common situations: The Vercel Connect credential was re-pointed to a different connector (re-install under another account) while the Paperclip connection still records the old connectorId/uid; Vercel's API is degraded and returns an unexpected envelope; the connector was rotated and uid changed server-side.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/96040c4f3d232690. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/tool-gateway.ts:3889

          {
            connectionId: connection.id,
            grantId: grant.id,
          },
        );
      }
      const request = vercelTokenRequest({
        credential: connection.externalCredential,
        grant,
        connectionId: connection.id,
        companyId: connection.companyId,
      });
      try {
        const token = await vercelConnect.getToken(request, resolveOptions);
        if (
          token.connector.id !== connection.externalCredential.connectorId &&
          token.connector.uid !== connection.externalCredential.connectorUid
        ) {
          throw new VercelConnectClientError(
            "vercel_connect_request_failed",
            502,
          );
        }
        await db
          .update(connectionGrants)
          .set({
            externalCredential: vercelGrantReference({
              credential: connection.externalCredential,
              token,
              subjectId: grant.externalCredential?.subjectId,
              verifiedAt: new Date(options.now?.() ?? Date.now()),
            }),
            status: "active",
            revokedAt: null,
            updatedAt: new Date(options.now?.() ?? Date.now()),
          })
          .where(

View on GitHub (pinned to 3f1d897a7c)