{"record":{"id":"619c8e844a02f9e8","repo":"paperclipai/paperclip","slug":"oauth-dynamic-client-registration-failed","errorCode":"oauth_dynamic_client_registration_failed","errorMessage":"OAuth dynamic client registration failed","messagePattern":"OAuth dynamic client registration failed","errorType":"http","errorClass":"HttpError","httpStatus":502,"severity":"error","filePath":"server/src/services/tool-access.ts","lineNumber":4418,"sourceCode":"      const dedicated = row.scope === \"company\"\n        && row.userSecretDefinitionId === null\n        && row.key.startsWith(CONNECTION_OWNED_SECRET_KEY_PREFIX);\n      if (dedicated && !referencedElsewhere.has(secretId)) owned.push(secretId);\n      else retained.push(secretId);\n    }\n    return { owned, retained };\n  }\n\n  /**\n   * Remove an app: a credential-revoking teardown, not a status flip (PAP-17119).\n   *\n   * Order is the security property. Every database-side access path closes\n   * first — grants, installs, the app-managed profile, gateway tokens minted\n   * against it, outstanding OAuth state, the catalog, and the connection itself\n   * — so the app is already undispatchable before the first call out to a secret\n   * provider. Secret revocation runs last, and each secret's ref survives until\n   * that secret is gone, so a provider that errors leaves the operation failed\n   * closed and resumable: the credential is already unresolvable (its row is\n   * marked deleted first), and retrying the same removal finishes the job.\n   *\n   * What stays behind is deliberate: the connection and application rows, their\n   * ids, names and activity keep working so a later reconnect reuses the same\n   * identity — but with no credential, no install and no profile, so\n   * reconnecting has to ask for fresh authentication and rebuild access.\n   */\n  async function removeConnection(\n    connectionId: string,\n    companyId?: string,\n    actor?: ActorInfo,\n    removalOptions: { confirmComposioChildren?: boolean } = {},\n  ): Promise<ToolConnectionRemovalResult> {\n    const connection = await getConnectionRow(connectionId, companyId);\n    const now = new Date();\n    const binding = actorBinding(actor);\n\n    if (isComposioConnection(connection)) {","sourceCodeStart":4400,"sourceCodeEnd":4436,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/tool-access.ts#L4400-L4436","documentation":"Dynamic client registration failure: the registration endpoint returned non-2xx or an invalid document, so no OAuth client could be created for this app on the fly. The provider rejecting the registration request is at fault.","triggerScenarios":"Thrown at server/src/services/tool-access.ts:4260 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Dynamic client registration failed at the provider. Confirm the provider supports DCR and that the registration request (redirect URIs, scopes) is valid, or pre-register a client and configure its credentials."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}