{"record":{"id":"3f6d108c67059c8e","repo":"jdx/mise","slug":"github-oauth-is-configured-for-not","errorCode":null,"errorMessage":"GitHub OAuth is configured for {}, not {}","messagePattern":"GitHub OAuth is configured for (.+?), not (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/github/oauth.rs","lineNumber":241,"sourceCode":"        return Ok(None);\n    };\n    let access_token = refreshed.access_token.clone();\n    cache.tokens.insert(cache_key.to_string(), refreshed);\n    if let Err(err) = write_cache_locked_async(cache_lock, cache).await {\n        warn!(\"failed to cache refreshed GitHub OAuth token: {err:#}\");\n    }\n    Ok(Some(access_token))\n}\n\nasync fn token_async(req: TokenRequest) -> Result<String> {\n    let settings = Settings::get();\n    let client_id = settings.github.oauth_client_id.trim();\n    let scopes = settings.github.oauth_scopes.trim();\n    if client_id.is_empty() {\n        bail!(\"GitHub OAuth is not configured. Set github.oauth_client_id first.\");\n    }\n    if !host_matches_settings(&req.host, &settings.github.oauth_api_url) {\n        bail!(\n            \"GitHub OAuth is configured for {}, not {}\",\n            api_host(&settings.github.oauth_api_url).unwrap_or_else(|| \"unknown host\".to_string()),\n            req.host\n        );\n    }\n\n    let canonical_host =\n        api_host(&settings.github.oauth_api_url).unwrap_or_else(|| req.host.clone());\n    let cache_key = cache_key(&canonical_host, client_id, scopes);\n    let cache = read_cache_async().await?;\n    if !req.force_refresh\n        && let Some(cached) = cache.tokens.get(&cache_key)\n        && reusable(cached)\n    {\n        return Ok(cached.access_token.clone());\n    }\n    if let Some(cached) = cache.tokens.get(&cache_key).cloned() {\n        // Passing the cached token as \"stale\" forces the refresh-token grant","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/github/oauth.rs#L223-L259","documentation":"token_async validates that the request host matches the host configured via github.oauth_api_url before exchanging tokens. If the caller asked for a token for a different host (e.g. a GHES instance) than the one the OAuth client is registered against, mise refuses with both hosts in the message to prevent sending credentials to the wrong server.","triggerScenarios":"token()/token_async() invoked with req.host = \"github.enterprise.example.com\" (or any host) while settings.github.oauth_api_url points at api.github.com (or another host) — the host strings do not match, so the exchange bails.","commonSituations":"Using a GitHub Enterprise Server URL for repos but leaving github.oauth_api_url at the default github.com; misconfigured oauth_api_url (wrong scheme/path or trailing host mismatch); a backend or plugin requesting tokens for a mirror/fork host; copy-pasted enterprise config without updating the API URL (or vice versa).","solutions":["Align github.oauth_api_url with the host you are authenticating to (set it to your GHES API URL for enterprise, or unset it to use github.com).","Remove the stale github.oauth_api_url setting if you actually intend to use github.com.","Update the requesting code/backend to ask for a token for the configured host instead of a different one.","Register a separate OAuth client on the enterprise instance and configure both oauth_client_id and oauth_api_url together."],"exampleFix":"# before: settings.toml\n[github]\noauth_client_id = \"Iv1.xxx\"\n# oauth_api_url defaults to github.com but requests target GHES\n// after\n[github]\noauth_client_id = \"Iv1.yyy\"  # client registered on GHES\noauth_api_url = \"https://github.enterprise.example.com/api/v3\"","handlingStrategy":"validation","validationCode":"// before requesting a token for a host\nconst settings = await getSettings();\nconst apiHost = new URL(settings.github?.oauth_api_url ?? 'https://github.com').host;\nif (apiHost !== requestHost) throw new Error(`oauth client is bound to ${apiHost}, not ${requestHost}`);","typeGuard":null,"tryCatchPattern":"try { const t = await githubToken(host); } catch (e) { if (String(e).includes('GitHub OAuth is configured for')) { console.error('Align github.oauth_api_url with the host being authenticated (GHES vs github.com)'); } else throw e; }","preventionTips":["Set github.oauth_api_url and github.oauth_client_id together when targeting GitHub Enterprise","Leave oauth_api_url unset for plain github.com usage","Register a dedicated OAuth app on the enterprise instance instead of reusing the github.com client id","Audit settings for stale oauth_api_url values after org/infra migrations"],"tags":["github","oauth","config","host-mismatch","authentication"],"backgroundTag":"invalid-config-value","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}