bad_verification_code 🔐 Authentication

GitHub OAuth: {"error":"bad_verification_code","error_description":"The code passed is incorrect or expired."}

The authorization code sent to GitHub’s token endpoint was already used, expired (10 minutes), or belongs to another OAuth app.

Seen on: REST API

Meaning

Codes are single-use. Double requests (React StrictMode, retries, page refresh on callback) consume the code, and the second exchange fails. Mixing client IDs between environments also fails.

Common causes

  • Code exchanged twice (StrictMode double effect, retries, refresh)
  • Code older than 10 minutes
  • client_id/secret from another OAuth app
  • redirect_uri differs from the authorize request

⚡ Quick fix

  1. Exchange the code once on the server and redirect away from the callback URL
  2. Guard against duplicate exchange
  3. Use matching client credentials per environment

Detailed fix by platform

JavaScript

  1. javascript
    // Next.js route handler — exchange once, then redirect
    const r = await fetch("https://github.com/login/oauth/access_token", { method: "POST", headers: { Accept: "application/json" }, body: new URLSearchParams({ client_id, client_secret, code }) });

How to diagnose

  1. Requests — How many exchanges per code?
  2. Age — Time since redirect
  3. App — Client ID matches?

🔧 Still not fixed?

Many errors look alike. If the steps above didn’t solve it, one of these is probably what you’re facing:

🧠 Still stuck? Analyze your error

Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.