{"record":{"id":"36755492157af782","repo":"paperclipai/paperclip","slug":"user-authorization-required","errorCode":"user_authorization_required","errorMessage":"User authorization is required","messagePattern":"User authorization is required","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":409,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":4606,"sourceCode":"        }\n      }\n    }\n    const resolution = userGrant\n      ? \"user\"\n      : resolveCredentialGrantKind(\n          connection.credentialPolicy,\n          actingUserId,\n          false,\n        );\n    if (resolution === \"user\" && userGrant) return userGrant;\n    if (resolution === \"user_authorization_required\") {\n      if (actingUserId)\n        await createUserAuthorizationInteraction(\n          session,\n          connection,\n          actingUserId,\n        );\n      throw new ToolGatewayHttpError(\n        409,\n        \"User authorization is required\",\n        \"user_authorization_required\",\n        {\n          connectionId: connection.id,\n          actingUserId,\n        },\n      );\n    }\n    return findOrganizationGrant();\n  }\n\n  async function resolveConnectedRemoteTool(\n    session: ToolGatewaySession,\n    tool: ToolGatewayDescriptor,\n  ) {\n    if (\n      tool.providerType !== \"mcp_remote_http\" ||","sourceCodeStart":4588,"sourceCodeEnd":4624,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/tool-gateway.ts#L4588-L4624","documentation":"The connection's credential policy resolved to 'user_authorization_required', meaning a human user's personal authorization is needed before the tool can run, and no user grant exists. If an actingUserId is present the gateway also creates a user-authorization interaction (asking the human to connect), then throws a 409.","triggerScenarios":"A tool on a connection whose credentialPolicy requires per-user authorization is invoked while resolveCredentialGrantKind returns 'user_authorization_required' — no active user-kind grant for the acting user and no delegation supplying userGrant.","commonSituations":"New user invoking an agent tool before linking their own OAuth account; token revoked/expired leaving no active grant; policy tightened from org-credential to user-credential after deployment.","solutions":["Complete the user-authorization interaction: have the acting user connect/authorize the connection in the UI","Create a user-kind connection grant for the acting user via the connections authorization flow","Change the connection credentialPolicy to an organization credential if personal grants are not desired"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const grant = await findActiveUserGrant(connection.id, actingUserId);\nif (!grant && resolveCredentialGrantKind(connection.credentialPolicy, actingUserId, false) === 'user_authorization_required') {\n  await createUserAuthorizationInteraction(session, connection, actingUserId); // surface connect prompt first\n}","typeGuard":null,"tryCatchPattern":"try { await runTool(...) } catch (e) { if (e.code === 'user_authorization_required') { await promptUserToAuthorizeConnection(e.details.connectionId); } else throw e; }","preventionTips":["Check connection authorization status in the UI before launching runs that use it","Onboard users through the connection flow before assigning them agent work","Watch for pending user_authorization interactions before scheduling autonomous runs"],"tags":["authorization","oauth","user-interaction"],"backgroundTag":"authentication-required","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}