Troubleshooting
Debug OAuth issues faster with proper logging and error handling
Where to start
Choose your path:
- Connection failing during OAuth? See Common OAuth errors below
- API calls returning errors? See Common integration issues below
- Token validation failing? See JWKS validation issues below
- Need to debug a specific flow? Check Telemetry headers below
- Everything seems fine, but it's not working? Start with Logging below
Quick fixes
OAuth errors you should return
These are standard OAuth error codes your server should return to Plaid:
| Error code | When to return | Fix |
|---|---|---|
access_denied | User cancelled authorization | Normal user behavior - log but don't alert |
invalid_grant | Authorization code expired or was reused | Reduce latency, expire codes in 10 min, enforce single-use |
temporarily_unavailable | Your server is overloaded or in maintenance | Check capacity, implement rate limiting, add monitoring |
JWKS and token validation issues
If Plaid encounters problems validating your ID tokens, connections will fail and your conversion rates will drop. These issues typically show up as authentication failures in your logs or low conversion metrics in the Data Partner Dashboard. Your Solutions Engineer may reach out to help troubleshoot.
Common JWKS problems and fixes
| Problem | How you would notice | What to check |
|---|---|---|
| ID token signature validation failing | Connection failures, user complaints | Verify kid in token header matches a key in your published JWKS |
| Key rotation issues | Sudden spike in auth failures after key rotation | Confirm new keys published to JWKS before removing old ones (24-hour overlap) |
| JWKS endpoint unreachable | All connections failing, Plaid can't validate any tokens | Check endpoint uptime, DNS resolution, firewall rules, and HTTPS configuration |
Logging
Even bulletproof OAuth servers have bad days. Good logging makes debugging 10x faster. Here's what to track.
Log these identifiers for every session
Include in your logs and support tickets:
| Identifier | Purpose |
|---|---|
state | Correlates redirect and token exchange. |
userId | Your internal authenticated user ID. |
timestamp | ISO-8601 timestamp of each request/response. |
request_id | Plaid request identifier (if included). |
correlation_id | Session-level identifier (tracks full OAuth flow). |
oauth_session_id (optional) | Your unique session tracker. |
Telemetry headers for debugging
To improve troubleshooting across the Plaid integration, implement these HTTP headers in your responses. These headers help trace requests through distributed systems and correlate logs between Plaid and your servers.
Required headers:
| Header | Purpose | Format |
|---|---|---|
Correlation-ID | Session-level identifier that remains constant across all endpoint calls in a single OAuth session. Use the same ID for all requests from initial authorization through token exchange. | UUID or alphanumeric string (16-64 chars) |
Request-ID | Unique identifier for each HTTP request. Changes with every endpoint call (/authorize, /token, /userinfo, etc.). | UUID or alphanumeric string (16-64 chars) |
When Plaid calls your token_endpoint (from your well-known configuration), your response should include:
HTTP/1.1 200 OK
Content-Type: application/json
Correlation-ID: sess_9a7f3c2d8e1b4f6a
Request-ID: req_4h8j2k9m3n7p5q1r
{
"access_token": "agstynmdygjdghabrgraeh...",
"expires_in": 900,
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "dhcsrtjsrgayvkdisfdgntshstu..."
}How to use these headers:
Correlation-ID: Generate once at the start of the OAuth flow (when user hits
/authorize). Include in all subsequent responses (/token,/userinfo, refresh requests, etc.) for that user's session.Request-ID: Generate a fresh ID for each HTTP request/response pair. Log this in your server logs alongside the Correlation-ID.
Benefits:
- Trace a complete OAuth session across multiple endpoint calls
- Correlate Plaid logs with Data Provider logs during troubleshooting
- Debug issues faster by identifying which specific request failed
- Support ticket resolution improved with precise request identification
Implementation tip: Store the Correlation-ID in session state or as a parameter in your OAuth flow so it persists across redirects.
JWKS validation issues
These issues only apply to OIDC implementations that issue ID tokens. Plain OAuth 2.0 implementations don't use JWKS.
| Error | Description | Resolution |
|---|---|---|
invalid_signature | ID token signature cannot be verified. | Ensure JWKS is reachable and current. |
kid_not_found | Token kid does not match any published key. | Verify correct key rotation and header values. |
jwks_uri_unreachable | JWKS endpoint not available. | Confirm HTTPS accessibility and DNS resolution. |
Common OAuth errors
| Error | Meaning | Resolution |
|---|---|---|
invalid_request | Missing/invalid parameter. | Validate query parameters; ensure redirect_uri and scope are present. |
unauthorized_client | Bad client credentials. | Confirm client_id/secret. |
invalid_grant | Code expired or reused. | Make codes one-time use; expire within < 10 min. |
redirect_uri_mismatch | URI does not match the registered value. | Must exactly match Plaid's redirect URI. |
temporarily_unavailable | DP downtime or maintenance. | Retry; notify Plaid of planned maintenance. |
Monitoring and alerting
Keep tabs on:
- HTTP status codes and latency for
authorize,token,userinfo, andjwks_uriendpoints - Error rates - Alert if > 2%
- OAuth and JWKS errors - Log with timestamp and state
When you need help
Opening a support ticket? Include:
statevalue- Timestamp and user ID
- Error message and HTTP status
- Request/response headers (mask the secrets!)
- Correlation-ID and Request-ID from telemetry headers
- Recent log entries surrounding the error
The more context you provide, the faster the resolution.
Common integration issues
Beyond standard OAuth errors, watch for these implementation problems:
Validation failures
Issue: API response validation fails because a field contains null instead of the expected data type (string, number, array, etc.).
Cause: Returning null for a field when the schema expects a typed value.
Resolution:
- Required fields: Return a value in the expected type. If data is unavailable, use an empty string (
"") for strings or an empty array ([]) for arrays. - Optional fields: Omit the field entirely from the response rather than setting it to
null.
// Don't do this
{
"email": null,
"phoneNumbers": null
}
// Do this instead
{
"email": "",
"phoneNumbers": []
}
// Or this (omit optional fields)
{
"email": ""
}Iteration limit exceeded
Issue: Plaid limits how many times it will call a paginated endpoint before throwing an error.
Cause: The nextOffset field (or equivalent pagination parameter) is set to null or an empty string on the final page instead of being omitted.
Resolution: On the last page of results, omit the nextOffset field completely. Don't set it to null, empty string, or 0.
Example:
// Don't do this (last page)
{
"data": [...],
"nextOffset": null
}
// Do this instead (last page)
{
"data": [...]
}No logs visible in Data Partner Dashboard
Issue: Data Providers trying to debug OAuth issues don't see logs in the Data Partner Dashboard.
Cause: Plaid only provides logs after the user successfully passes initial authentication steps. If the OAuth flow fails during authorization or before the token exchange completes, logs will not be available.
Resolution: Contact Plaid support to review internal logs and identify where the flow broke. Common pre-log issues include: invalid client_id, HTTPS errors, or redirect URI mismatch.
invalid_grant during refresh
Issue: Refresh token flow fails with invalid_grant error during background updates.
Cause: Refresh token expired before Plaid attempted to use it. This error can occur when the refresh token lifetime is set too short or when the DP revokes tokens after a period of inactivity.
Resolution:
- Set refresh token expiration to 13+ months
- Don't use inactivity timeouts on refresh tokens
- If revocation is necessary, coordinate with Plaid to avoid breaking active connections
User identifier rejected (consistency key)
Issue: Connection fails because the user identifier (consistency key) returned in the id_token sub field or /customers/current is fewer than seven characters.
Cause: Consistency key too short to meet minimum requirements.
Resolution: Use a longer identifier or a prefix with the institution code, with a minimum length of seven characters.
// Too short
{"sub": "12345"}
// Acceptable length
{"sub": "user_12345"}