# Fix Stripe Connect OAuth failing when the account link expires

## TL;DR
Stripe Connect account links expire after a short window, so a link created too early is dead by the time the user clicks it. Create the account link right before presenting it and send the user through immediately. If it expired, just create a fresh link; the old one cannot be revived.

## The error
```text
Stripe Connect OAuth failed
Error: This account link has expired. Please create a new one.
```

## Use this skill
Agent? Search Vectle for this error:
```bash
curl -s "https://vectle.com/api/v1/search?q=stripe connect oauth account link expired failed"
```

## Fix it

### Step 1: Create a fresh account link

```bash
Call the Stripe API to create a new account link for the connected account.
```

Expected: You get a new URL with a fresh expiry window.

### Step 2: Present it to the user immediately

```bash
Send the user to the link right away instead of queueing it in an email drip.
```

Expected: The user opens a live link.

### Step 3: Move link creation to click time

```bash
Change your onboarding flow so the link is created when the user clicks continue, not when the account is created.
```

Expected: Links are always minutes old, never hours old, when opened.

### Step 4: Handle expiry gracefully in the UI

```bash
If the user lands on an expired link, show a button that generates a new one instead of an error page.
```

Expected: Expired links become a one-click recovery instead of a support ticket.

### Step 5: Verify onboarding completes

```bash
Walk a test account through the full Connect onboarding.
```

Expected: The account finishes onboarding with no expiry errors.

## When this applies

- Stripe Connect onboarding fails with expired account links
- Users report dead onboarding links hours after signup
- You create account links in batch jobs

## When it doesn't

- The link works but onboarding stalls later (check the account requirements)
- The error is about OAuth scopes (check the Connect settings)
- You use Express accounts with a different onboarding flow

## Compatibility

Stripe Connect account links API. Applies to Custom and Express onboarding flows.

## Variant phrasings

### stripe account link expired error

Same failure. Fresh links are the only fix; expired ones are unrecoverable by design.

### stripe connect onboarding link invalid

Invalid covers expired plus already-used. Create a new link either way.

### stripe connect oauth failed account link

If the failure is at the OAuth step rather than the link step, check your Connect client id and redirect URI.

## Why it happens

Account links are short-lived by design so they cannot be reused or phished later. Creating them far ahead of the user action, in a nightly job or at signup, guarantees they die before use. The flow assumes link creation and link opening happen close together.

## Edge cases

- Account links are single-session; sharing one link across users fails for everyone but the first
- Test-mode and live-mode links are not interchangeable
- If users consistently take days to click, switch to an onboarding flow that does not depend on link timing

## If it still fails

- Reproduce in test mode with test cards before touching live config.
- Read the full API error object; the code and decline code name the next step.
- Check the provider status page; payment API incidents look like integration bugs.
- Never retry live charges blindly; verify state first and use idempotency keys.
- For money-movement confusion, reconcile against the dashboard before writing code.

## Prevention

- Exercise the full payment flow in test mode on every deploy.
- Alert on failed payment webhooks, not just API errors.
- Keep idempotency keys on every charge-creating call.
- Reconcile payouts against the dashboard on a schedule.
- Document the retry and dunning policy so agents and humans agree.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_66b9dxBh3gkSTRrFmn_uaQ
