paperclipai/paperclip · error · HttpError
Remote app returned an error
Error message
Remote app returned an error
What it means
Upstream error translation: the remote app's OAuth-protected endpoint returned an error response, which is wrapped into HttpError 502 with the discovered provider metadata persisted for debugging. The remote provider's failed response is at fault.
Solutions
- The remote app returned an error during auth. Check the app's configuration and provider-side logs, then retry the connection.
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at server/src/services/tool-access.ts:2914 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-08-18).
Data as JSON: /api/errors/4d6a21ec23594c45.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/tool-access.ts:3058
agentId: string;
issueId: string | null;
projectId: string | null;
routineId: string | null;
}) {
const bindings = await db.select().from(toolProfileBindings).where(eq(toolProfileBindings.companyId, input.companyId));
const matchingBindings = bindings.filter((binding) => {
if (binding.targetType === "company") return binding.targetId === input.companyId;
if (binding.targetType === "agent") return binding.targetId === input.agentId;
if (binding.targetType === "issue") return Boolean(input.issueId && binding.targetId === input.issueId);
if (binding.targetType === "project") return Boolean(input.projectId && binding.targetId === input.projectId);
if (binding.targetType === "routine") return Boolean(input.routineId && binding.targetId === input.routineId);
return false;
});
const profileIds = profileIdsInBindingOrder(narrowestScopeBindings(matchingBindings));
if (profileIds.length === 0) return false;
const profiles = await db.select().from(toolProfiles).where(and(
eq(toolProfiles.companyId, input.companyId),
inArray(toolProfiles.id, profileIds),
));
const activeProfileIds = profiles
.filter((profile) => profile.status === "active")
.map((profile) => profile.id);
if (activeProfileIds.length === 0) return false;
const entries = await db.select().from(toolProfileEntries).where(and(
eq(toolProfileEntries.companyId, input.companyId),
inArray(toolProfileEntries.profileId, activeProfileIds),
));
return activeProfileIds.some((profileId) => {
const profileEntries = entries.filter((entry) => entry.profileId === profileId);
const exactBrokerEntries = profileEntries.filter((entry) =>
entry.selectorType === "tool_name"
&& entry.toolName === CONNECTION_TOKEN_MINT_TOOL_NAME
&& Object.keys(asRecord(entry.conditions)).length === 0
);
if (exactBrokerEntries.some((entry) => entry.effect === "exclude")) return false;
return exactBrokerEntries.some((entry) => entry.effect === "include");View on GitHub (pinned to 01ad858492)