## TL;DR

Send a redirect_uri that matches the registered callback URL exactly, or omit redirect_uri and let GitHub use the registered one. GitHub compares the strings strictly, so a trailing slash, a port, or http vs https is enough to fail. Match it exactly.

```
github oauth: The redirect_uri MUST match the registered callback URL for this application
```

## Steps

1. Open the GitHub OAuth app settings and copy the Authorization callback URL exactly as registered. Expected: you have the canonical string.

2. Log the redirect_uri your client actually sends on the authorization request. Expected: you can diff the two strings.

3. Fix the mismatch: change the sent value to the registered one, character for character. Expected: the two strings are identical.

4. If your app runs on multiple hosts or ports (local dev vs production), register each callback URL the app actually uses, or route all environments through one callback that dispatches internally. Expected: every environment has a matching registration.

5. Keep the same redirect_uri on the token exchange call. Expected: the exchange uses the identical string.

6. Retry the OAuth flow from the start. Expected: GitHub redirects back with a code instead of the mismatch error.

## Use this when

- GitHub returns exactly "The redirect_uri MUST match the registered callback URL".
- A generated client builds the callback URL dynamically and it drifts from the registered one.
- The app moved hosts, ports, or schemes after registration.

## Not for this skill when

- The client id is wrong or the app was deleted - those fail differently.
- Scopes or permissions are the problem - this error is only about the URL.
- The provider is not GitHub; matching rules differ elsewhere.

## Variant phrasings

- GitHub OAuth redirect_uri mismatch
- GitHub callback URL must match registered
- GitHub OAuth redirect uri does not match

## Why it happens

The redirect URI is a security control: it pins where codes go. GitHub enforces an exact string match, and generated clients love to construct the URL at runtime (adding ports, paths, or trailing slashes the registration does not have). Dev/prod environment differences make it worse.

## Edge cases

- A single OAuth app can register only one callback URL; multi-environment setups need separate apps or a single dispatching callback.
- URL-encoding differences (encoded vs raw slashes) count as mismatches; send it plain and let the HTTP library encode once.
- Some frameworks append a trailing slash to routes; the registered URL must include it if the app sends it.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_0-5Z5OBV66waMK1EvBnTUA
