paperclipai/paperclip · error

Paperclip couldn’t preserve this sign-in while refreshing yo

Error message

Paperclip couldn’t preserve this sign-in while refreshing your account.

What it means

During OAuth reauthentication in ConnectionSetupFlow, after the cloud indicates a reauthentication flow, the code needs a destination (the dialog popup or the current window) plus a persisted handoff to carry session state. If the popup is missing, already closed, or the start result carries no handoff, the sign-in cannot be preserved across the account refresh, so the flow throws this user-facing error.

Source

Thrown at ui/src/features/connections/ConnectionSetupFlow.tsx:707

      setOAuthError("The sign-in window closed. If authorization did not finish, try again.");
      setAuthorizationFallbackUrl(null);
      onPhaseChange?.("needs_retry");
    }, 1_000);
    return () => window.clearInterval(timer);
  }, [host, oauthPhase, onPhaseChange]);

  const prepareAndOpenOAuth = useCallback(async (
    start: Pick<ToolOAuthStartResult, "authorizationUrl" | "handoff">,
  ) => {
    oauthHandoffAbortRef.current?.abort();
    const controller = new AbortController();
    oauthHandoffAbortRef.current = controller;
    try {
      const target = await prepareOAuthNavigation(start, { signal: controller.signal });
      if (target.kind === "reauthentication") {
        const destination = host === "dialog" ? oauthPopupRef.current : window;
        if (!destination || destination.closed || !start.handoff) {
          throw new Error("Paperclip couldn’t preserve this sign-in while refreshing your account.");
        }
        savePendingCloudHandoff(start.handoff.session, destination.sessionStorage);
        setOAuthPhase("starting");
      } else {
        setAuthorizationHost(target.host);
        setOAuthPhase("redirecting");
      }
      openAuthorization(target.url);
    } catch (error) {
      if (controller.signal.aborted) return;
      setOAuthPhase("error");
      setOAuthError(error instanceof Error ? error.message : "Paperclip couldn’t start secure sign-in. Try again.");
      onPhaseChange?.("needs_retry");
    } finally {
      if (oauthHandoffAbortRef.current === controller) oauthHandoffAbortRef.current = null;
    }
  }, [host, onPhaseChange, openAuthorization]);

View on GitHub (pinned to 01ad858492)

Solutions

  1. Allow popups for the Paperclip origin and restart the connection setup.
  2. Retry the connection flow in the same tab (non-dialog host) if popups cannot be enabled.
  3. Check the server response: if `handoff` is missing on a reauthentication start, fix the backend to return it.

Example fix

// before
const destination = host === "dialog" ? oauthPopupRef.current : window;
if (!destination || destination.closed || !start.handoff) throw new Error("...");
// after
if (host === "dialog" && (!oauthPopupRef.current || oauthPopupRef.current.closed)) {
  reopenDialogAndRetry(start); // re-open popup instead of failing
  return;
}
const destination = host === "dialog" ? oauthPopupRef.current : window;
Defensive patterns

Strategy: try-catch

Validate before calling

function dialogReady(ref: React.RefObject<Window | null>): boolean {
  return !!ref.current && !ref.current.closed;
}

Type guard

function canPreserveSignIn(dest: Window | null, handoff: unknown): handoff is { session: string } {
  return !!dest && !dest.closed && !!handoff && typeof handoff === "object" && "session" in handoff;
}

Try / catch

try {
  await beginOAuth(start, { host: "dialog" });
} catch (e) {
  if (e instanceof Error && e.message.includes("preserve this sign-in")) {
    showPopupBlockedHelp(); // instruct user to allow popups, offer same-tab retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the OAuth start flow when the provider requires reauthentication and: `oauthPopupRef.current` is null or closed (host === "dialog"), `window` unavailable, or `start.handoff` is undefined.

Common situations: Browser blocked the popup so the ref is null; user closed the dialog before this step; server returned a reauthentication target but omitted the handoff payload; popup closed by user between steps.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/b0028da557f5572f. Report an issue: GitHub.