decolua/9router · warning
xai discovery ${field} is invalid: ${err.message}
Error message
xai discovery ${field} is invalid: ${err.message} What it means
validateXaiOAuthEndpoint parses the discovered endpoint with the URL constructor; when parsing fails it rethrows a wrapped error naming which field failed and the underlying URL parser message. It guards the OAuth flow from garbage endpoint strings in the xAI discovery document. discoverXaiEndpoints normally catches this and falls back to static x.ai endpoints.
Source
Thrown at src/lib/oauth/providerHelpers.js:8
const BASE64_BLOCK_SIZE = 4;
function validateXaiOAuthEndpoint(rawUrl, field) {
const value = String(rawUrl || "").trim();
if (!value) throw new Error(`xai discovery ${field} is empty`);
let parsed;
try { parsed = new URL(value); } catch (err) {
throw new Error(`xai discovery ${field} is invalid: ${err.message}`);
}
if (parsed.protocol !== "https:") throw new Error(`xai discovery ${field} must use https: ${value}`);
const host = parsed.hostname.toLowerCase().trim();
if (host !== "x.ai" && !host.endsWith(".x.ai")) {
throw new Error(`xai discovery ${field} host ${host} is not on x.ai`);
}
return value;
}
function decodeXaiIdTokenEmail(idToken) {
if (!idToken || typeof idToken !== "string") return undefined;
const parts = idToken.split(".");
if (parts.length !== 3) return undefined;
try {
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
const padding = (BASE64_BLOCK_SIZE - (base64.length % BASE64_BLOCK_SIZE)) % BASE64_BLOCK_SIZE;
const json = Buffer.from(base64 + "=".repeat(padding), "base64").toString("utf8");
const payload = JSON.parse(json);View on GitHub (pinned to 90b52e06ff)
Solutions
- Let discoverXaiEndpoints' try/catch fall back to the static XAI_CONFIG endpoints; confirm your caller doesn't rethrow.
- Inspect the raw discovery response (curl the discoveryUrl) to see what malformed value is being served.
- If you control discoveryUrl, point it back at the official xAI well-known endpoint.
- Pre-validate with new URL(value) in a try/catch before calling the OAuth flow.
Example fix
// before
const tokenUrl = validateXaiOAuthEndpoint('x.ai/api/oauth/token', 'token_endpoint'); // throws: Invalid URL
// after
const tokenUrl = validateXaiOAuthEndpoint('https://x.ai/api/oauth/token', 'token_endpoint'); Defensive patterns
Strategy: validation
Validate before calling
function isParseableUrl(v) {
if (typeof v !== 'string') return false;
try { new URL(v.trim()); return true; } catch { return false; }
}
// use: isParseableUrl(data.token_endpoint) ? validateXaiOAuthEndpoint(data.token_endpoint, 'token_endpoint') : fallback Type guard
function isHttpUrl(v) {
try { return new URL(String(v).trim()) instanceof URL; } catch { return false; }
} Try / catch
try {
const tokenUrl = validateXaiOAuthEndpoint(data.token_endpoint, 'token_endpoint');
// use tokenUrl
} catch (err) {
if (/xai discovery .* is invalid:/.test(err.message)) {
console.warn('xAI discovery endpoint unparseable, using static fallback', err.message);
return { authorizeUrl: XAI_CONFIG.authorizeUrl, tokenUrl: XAI_CONFIG.tokenUrl };
}
throw err;
} Prevention
- Pre-parse discovered URLs with new URL() before handing them to strict validators.
- Curl the discovery URL to inspect the actual served document when errors repeat.
- Only use the official xAI well-known discovery URL; mirrors often emit malformed values.
- Keep the static XAI_CONFIG endpoints configured for fallback.
When it happens
Trigger: The discovery JSON's authorization_endpoint or token_endpoint is present but not a parseable URL — e.g. 'x.ai/oauth/authorize' (no scheme), 'not-a-url', relative paths, or strings containing spaces/control characters.
Common situations: Misconfigured reverse proxy returning HTML or a truncated string, a modified XAI_CONFIG.discoveryUrl pointing at a mock or third-party mirror, or unit tests feeding malformed fixtures.
Related errors
- xai discovery ${field} is empty
- `xai discovery ${field} must use https: ${value}`
- `xai discovery ${field} host ${host} is not on x.ai`
- xAI OAuth session not found; restart the login flow and past
- Missing xAI authorization code
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/763d1e9d74ceed3e.
Report an issue: GitHub.