Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MomenSherif/react-oauth/llms.txt

Use this file to discover all available pages before exploring further.

@react-oauth/github represents every OAuth failure as a plain Error object with a code property added. Four codes cover every failure mode the hook can produce.

Error codes

CodeConstantDescription
OA001OAuthErrorCode.POPUP_CLOSEDThe user closed the popup window before completing authorization.
OA002OAuthErrorCode.POPUP_BLOCKEDThe browser blocked the popup window.
OA003OAuthErrorCode.STATE_MISMATCHThe state parameter returned by GitHub did not match the value sent. Possible CSRF attack.
OA004OAuthErrorCode.MISSING_CODEThe authorization code was not found in the OAuth callback URL.

Error object structure

All OAuth errors are standard Error instances extended with a code property:
type OAuthError = Error & {
  code: OAuthErrorCode; // e.g. "OA001"
};
The error.name property is set to "OAuthError" and error.message contains a human-readable description like "OA001 The Popup Closed".

Checking for OAuth errors

Use OAuthError.isOAuthError() to distinguish OAuth-specific errors from unexpected runtime errors before checking the code:
import { OAuthError } from '@react-oauth/github';

onError: error => {
  if (OAuthError.isOAuthError(error)) {
    // error.code is now typed as OAuthErrorCode
    console.log('OAuth error code:', error.code);
  } else {
    // Unexpected runtime error
    console.error('Unexpected error:', error);
  }
}
The type guard checks that the value is an Error instance, has a code property, and that code is one of the four known OAuthErrorCode values.

Complete switch-case example

import { useGitHubLogin, OAuthError, OAuthErrorCode } from '@react-oauth/github';

function LoginButton() {
  const [errorMessage, setErrorMessage] = React.useState<string | null>(null);

  const { initiateGitHubLogin, isLoading } = useGitHubLogin({
    clientId: 'your-github-client-id',
    redirectUri: 'http://localhost:3000/callback',
    onSuccess: response => {
      setErrorMessage(null);
      // send response.code to your backend
    },
    onError: error => {
      if (OAuthError.isOAuthError(error)) {
        switch (error.code) {
          case OAuthErrorCode.POPUP_CLOSED:
            // User closed the popup — not necessarily an error worth showing
            setErrorMessage(null);
            break;

          case OAuthErrorCode.POPUP_BLOCKED:
            // Browser prevented the popup from opening
            setErrorMessage(
              'Your browser blocked the sign-in popup. Please allow popups for this site and try again.',
            );
            break;

          case OAuthErrorCode.STATE_MISMATCH:
            // Security check failed — treat as a hard error
            setErrorMessage(
              'Authentication failed due to a security check. Please try again.',
            );
            break;

          case OAuthErrorCode.MISSING_CODE:
            // GitHub returned a callback without a code
            setErrorMessage(
              'GitHub did not return an authorization code. Please try again.',
            );
            break;

          default:
            setErrorMessage('An unexpected authentication error occurred.');
        }
      } else {
        setErrorMessage('An unexpected error occurred. Please try again.');
      }
    },
  });

  return (
    <div>
      <button onClick={initiateGitHubLogin} disabled={isLoading}>
        {isLoading ? 'Connecting...' : 'Sign in with GitHub'}
      </button>
      {errorMessage && <p role="alert" style={{ color: 'red' }}>{errorMessage}</p>}
    </div>
  );
}

Error-by-error guidance

OA001 — Popup closed

The user dismissed the popup before completing authorization. This is the most common “error” and often requires no action — the user simply changed their mind. Best practice: Clear any loading state silently. Only show a message if you want to offer a retry.

OA002 — Popup blocked

The browser’s popup blocker prevented the window from opening. This happens when the login is not triggered directly by a user gesture (e.g., called in a setTimeout or useEffect rather than a click handler). Best practice: Show a clear message asking the user to allow popups for your site and try again. Provide a retry button.
onError: error => {
  if (OAuthError.isOAuthError(error) && error.code === OAuthErrorCode.POPUP_BLOCKED) {
    setShowPopupWarning(true); // Render a banner with instructions
  }
}

OA003 — State mismatch

The state value returned by GitHub does not match the one the hook sent. This indicates a possible CSRF attack or a browser extension interfering with the OAuth redirect. Best practice: Treat this as a security-critical error. Show a generic “authentication failed” message. Do not expose technical details to the user.

OA004 — Missing code

GitHub’s callback URL did not contain a code parameter. This can happen if the user denied access, or if there is a misconfiguration in your OAuth App settings. Best practice: Log the full error for debugging and show a retry option to the user.

Build docs developers (and LLMs) love