paperclipai/paperclip · error · HttpError

oauth_refresh_outcome_unknown

oauth_refresh_outcome_unknown

Error message

The previous OAuth refresh did not finish. Reconnect this app before retrying.

What it means

Refresh-lease contention guard: the conditional UPDATE claiming the connection's refresh lease (config refreshLease id null) matched zero rows because another process is mid-refresh. Prevents concurrent token refreshes from clobbering each other; the concurrent refresh is at fault.

Source

Thrown at server/src/services/tool-access.ts:4705

        .where(eq(toolConnections.id, connection.id))
        .returning();
      if (!updatedConnection) throw notFound("Tool connection not found");

      const remainingConnections = await tx
        .select({ id: toolConnections.id })
        .from(toolConnections)
        .where(and(
          eq(toolConnections.applicationId, updatedConnection.applicationId),
          ne(toolConnections.status, "archived"),
        ))
        .limit(1);

      let applicationArchived = false;
      if (remainingConnections.length === 0) {
        const [application] = await tx
          .update(toolApplications)
          .set({ status: "archived", archivedAt: now, updatedAt: now })
          .where(and(
            eq(toolApplications.id, updatedConnection.applicationId),
            ne(toolApplications.status, "archived"),
          ))
          .returning({ id: toolApplications.id });
        applicationArchived = Boolean(application);
      }

      return { connection: updatedConnection, applicationArchived };
    });

    // Only now, with every access path closed, revoke the credentials. Each
    // `secrets.remove` marks the row deleted before it calls the provider, so a
    // provider error leaves an unresolvable secret and a resumable removal
    // rather than a half-open app.
    const candidateSecretIds = [
      ...connection.credentialRefs.map((ref) => ref.secretId),
      ...connection.credentialSecretRefs.map((ref) => ref.secretId),
      ...grantRows.flatMap((grant) => (grant.credentialSecretRefs ?? []).map((ref) => ref.secretId)),

View on GitHub (pinned to 01ad858492)

Solutions

  1. A previous refresh attempt is incomplete/locked. Reconnect the app to reset the OAuth state before retrying.
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at server/src/services/tool-access.ts:4547 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/49ce17625001ddfb. Report an issue: GitHub.