Skip to main content
If Connect looks successful once, then later clicks never open OAuth and the integration stays disconnected in your UI, the user likely still has a PENDING credential. That happens when OAuth finishes but required post-OAuth options are not set. The next installFlow.start resumes that incomplete install instead of starting a new one. This is not a blocked popup. If onError reports OAuthBlockedError, use OAuth popup is blocked when connecting an integration.

Symptoms

  • First Connect appears to complete OAuth, then the integration never shows as enabled.
  • Dashboard or getUser() shows credentialStatus: "PENDING" (sometimes labeled pending configuration).
  • Later Connect clicks do not open an OAuth window. The Headless flow goes straight to postOptions, or appears stuck with no UI.
  • onComplete never fires. Your onNext handler may call setPostOptions({}) and return.

Cause

Headless install is a sequence of stages. OAuth is only one of them. After OAuth, some integrations emit PostOptionsStage (a site, workspace, or similar required field). setPostOptions saves those values and completes the connection. If you skip the stage or pass an empty object, Paragon can still create a credential, but it stays PENDING because required post-OAuth options were never provided. The next installFlow.start for that user and integration prefers completing the pending credential. You never get a new OAuth popup, so it looks like Connect is broken. installFlow.cancel documents this: if OAuth completed but required post-OAuth options did not, cancel removes the PENDING credential. After a reload, call uninstallIntegration yourself.

Fix

1. Confirm the credential is PENDING

2. Complete post-OAuth options in onNext

Handle postOptions the same way you handle preOptions: render the fields from next.options and pass the selected values into setPostOptions. The SDK example uses field ids from that stage (for example JIRA_CLOUD_ID).

3. Clear a stuck PENDING credential

  1. If the install flow is still in memory, call paragon.installFlow.cancel(). That uninstalls a PENDING credential created in the current session.
  2. If the page reloaded, call paragon.uninstallIntegration("<integration-type>") (and selectedCredentialId when using multiple accounts).
  3. Start installFlow.start again, with a real postOptions handler.

Prevention

  • Implement PostOptionsStage for every integration you enable. A handler that only works for integrations without post-OAuth fields will fail the first time you add one that has them.
  • After onComplete, check getUser() and refuse to treat PENDING as connected.
  • If the user abandons Connect after OAuth, call installFlow.cancel() so they do not remain PENDING.