{"record":{"id":"eecd34e1e539899b","repo":"paperclipai/paperclip","slug":"oauth-challenge","errorCode":"oauth_challenge","errorMessage":"This app needs you to sign in.","messagePattern":"This app needs you to sign in\\.","errorType":"http","errorClass":"HttpError","httpStatus":502,"severity":"error","filePath":"server/src/services/tool-access.ts","lineNumber":3050,"sourceCode":"        limit,\n        windowSeconds: 3600,\n      });\n    }\n  }\n\n  async function hasExplicitConnectionTokenMintProfileGrant(input: {\n    companyId: string;\n    agentId: string;\n    issueId: string | null;\n    projectId: string | null;\n    routineId: string | null;\n  }) {\n    const bindings = await db.select().from(toolProfileBindings).where(eq(toolProfileBindings.companyId, input.companyId));\n    const matchingBindings = bindings.filter((binding) => {\n      if (binding.targetType === \"company\") return binding.targetId === input.companyId;\n      if (binding.targetType === \"agent\") return binding.targetId === input.agentId;\n      if (binding.targetType === \"issue\") return Boolean(input.issueId && binding.targetId === input.issueId);\n      if (binding.targetType === \"project\") return Boolean(input.projectId && binding.targetId === input.projectId);\n      if (binding.targetType === \"routine\") return Boolean(input.routineId && binding.targetId === input.routineId);\n      return false;\n    });\n    const profileIds = profileIdsInBindingOrder(narrowestScopeBindings(matchingBindings));\n    if (profileIds.length === 0) return false;\n    const profiles = await db.select().from(toolProfiles).where(and(\n      eq(toolProfiles.companyId, input.companyId),\n      inArray(toolProfiles.id, profileIds),\n    ));\n    const activeProfileIds = profiles\n      .filter((profile) => profile.status === \"active\")\n      .map((profile) => profile.id);\n    if (activeProfileIds.length === 0) return false;\n    const entries = await db.select().from(toolProfileEntries).where(and(\n      eq(toolProfileEntries.companyId, input.companyId),\n      inArray(toolProfileEntries.profileId, activeProfileIds),\n    ));\n    return activeProfileIds.some((profileId) => {","sourceCodeStart":3032,"sourceCodeEnd":3068,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/tool-access.ts#L3032-L3068","documentation":"Auth-challenge translation: a request to the remote app returned 401/402-style responses indicating the stored OAuth authorization is absent or stale, so the user must (re)authorize. Surfaced to the UI as an oauth_challenge rather than a raw upstream error; the connection's missing/stale authorization is at fault.","triggerScenarios":"Thrown at server/src/services/tool-access.ts:2906 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Complete the sign-in/OAuth flow for this app (reconnect it from the connections UI) so an authorized session exists."],"exampleFix":null,"handlingStrategy":"fallback","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"}