Troubleshooting
Error Codes
All SDK errors are instances of NexlaConnectError with a machine-readable code property. Always branch on code, not on message.
| Code | When it occurs | Resolution |
|---|---|---|
POPUP_BLOCKED | Browser blocked the OAuth popup | Prompt user to allow popups for your site, then retry |
OAUTH_CANCELLED | User closed the popup without completing auth | No action needed — treat as a user-initiated cancel |
OAUTH_TIMEOUT | OAuth flow did not complete within 5 minutes | Retry; check network connectivity |
OAUTH_ERROR | Connector returned an error during authorization | Show the error description to the user |
MISSING_PROVIDER | Hook called outside NexlaConnectProvider | Move the component inside a NexlaConnectProvider |
API_ERROR | Nexla API returned an unexpected error | Check error.message for details; inspect network requests |
RATE_LIMITED | Nexla API returned 429 | Wait and retry; reduce request frequency |
REQUEST_TIMEOUT | API request exceeded timeout | Check network; retry |
APPLICATION_MISMATCH | The applicationId prop doesn't match the SDK application linked to the service key | Check that you're using the correct service key for the configured applicationId. Go to Settings → SDK Applications to verify the mapping. |
CONNECTOR_NOT_FOUND | Connector key not in the connectors array | Add the connector key to NexlaConnectProvider.connectors |
import { NexlaConnectError } from '@nexla/react-sdk';
function handleError(error: NexlaConnectError) {
switch (error.code) {
case 'POPUP_BLOCKED':
showBanner('Allow popups for this site to connect integrations.');
break;
case 'OAUTH_CANCELLED':
// Expected — user closed the window
break;
case 'OAUTH_TIMEOUT':
showBanner('Authorization timed out. Please try again.');
break;
case 'APPLICATION_MISMATCH':
console.error('Service key does not match the configured applicationId.');
break;
case 'CONNECTOR_NOT_FOUND':
console.error(`Connector "${error.connector}" is not in the enabled connectors list.`);
break;
case 'MISSING_PROVIDER':
console.error('useNexlaConnect called outside NexlaConnectProvider');
break;
default:
console.error(`Nexla error [${error.code}]:`, error.message);
}
}
Common Issues
Application ID mismatch on startup
Symptom: NexlaConnectError: APPLICATION_MISMATCH thrown on provider mount.
Cause: The applicationId prop doesn't match the SDK application that the service key is linked to. Each service key is auto-provisioned for a specific SDK application.
Fix: Go to Settings → SDK Applications in the Nexla UI and verify which service key belongs to which application. Either:
- Update the
applicationIdprop to match the service key's application, or - Use the service key that was provisioned for the configured
applicationId
If the service key isn't linked to any SDK application, you'll see a message instructing you to create one in the dashboard.
Styled components are unstyled
Symptom: NexlaConnectButton or NexlaConnectModal renders without Nexla styling.
Cause: NexlaThemeProvider is missing or not an ancestor of the styled components.
Fix: Wrap styled components in NexlaThemeProvider:
<NexlaConnectProvider {/* ...props */}>
<NexlaThemeProvider mode="light"> {/* ← required */}
<NexlaConnectButton connector="CONNECTOR_KEY" />
</NexlaThemeProvider>
</NexlaConnectProvider>
"Hook called outside NexlaConnectProvider"
Symptom: NexlaConnectError: MISSING_PROVIDER at runtime.
Cause: A component using useNexlaConnect, useCredentials, or useConnectorForm is rendering outside the provider tree.
Fix: Ensure NexlaConnectProvider is an ancestor in the tree — typically at the app root or page level.
OAuth popup is blocked
Symptom: NexlaConnectError: POPUP_BLOCKED thrown immediately on connect().
Cause: The browser's popup blocker is active. This typically happens when connect() is not called from a direct user interaction (e.g. it's called from a useEffect or after an await).
Fix: Call connect() directly inside an event handler:
// ✅ Called from click handler — popup allowed
<button onClick={() => connect('CONNECTOR_KEY')}>Connect</button>
// ❌ Called after async work — popup may be blocked
async function handleClick() {
await doSomeWork(); // browser loses the user gesture context
await connect('CONNECTOR_KEY'); // popup may be blocked
}
If you must call after an await, consider showing a second "Authorize" button for the user to click explicitly.
Credentials not updating after connect
Symptom: useCredentials still returns the old list after a successful connect().
Cause: This should not happen in normal use — the SDK updates credentials in context automatically after connect(). If it occurs, check that you're not rendering multiple isolated NexlaConnectProvider instances.
Fix: Call refreshCredentials() to force a refetch:
const { connect, refreshCredentials } = useNexlaConnect();
const credential = await connect('CONNECTOR_KEY');
await refreshCredentials(); // force sync if needed
TypeScript: optional props compiler errors
Symptom: TS error when spreading optional SDK props onto a component.
Cause: The SDK's tsconfig uses exactOptionalPropertyTypes: true. Setting an optional prop to undefined explicitly is a type error.
Fix: Use conditional spreading instead of prop={undefined}:
// ❌ type error with exactOptionalPropertyTypes
<NexlaConnectProvider theme={undefined} />
// ✅ omit the prop entirely, or conditionally spread
<NexlaConnectProvider {...(theme ? { theme } : {})} />
Radix UI peer dependency warnings
Symptom: Console warning about missing peer dependency for a @radix-ui/* package.
Cause: Styled components are imported but the Radix UI peer dependencies are not installed.
Fix: Install the optional peer dependencies (see Installation), or only import headless hooks and avoid styled component imports entirely.
Debugging Tips
Inspect the context state
Add a debug component inside the provider to inspect current state:
function NexlaDebug() {
const { credentials, connectors, loading, error, connectingConnector } = useNexlaConnect();
if (process.env.NODE_ENV !== 'development') return null;
return (
<pre style={{ fontSize: 11, opacity: 0.6 }}>
{JSON.stringify({ loading, connectingConnector, errorCode: error?.code,
credentialCount: credentials.length, connectorCount: connectors.length }, null, 2)}
</pre>
);
}
Enable network logging
All SDK API calls use plain fetch. Enable network logging in your browser DevTools (Network tab, filter by /admin-api) to inspect request/response payloads, status codes, and headers.
Check token exchange
If all API calls are returning 401, the service key exchange may have failed silently. Add an onError callback to the provider to catch early auth errors:
<NexlaConnectProvider
onError={(err) => console.error('[Nexla]', err.code, err.message)}
// ...
>
Getting Help
If you're stuck after working through this guide, reach out to Nexla support with:
- The exact
NexlaConnectError.codevalue - The
error.messagetext - The connector key involved (if applicable)
- Browser and React version