{"record":{"id":"763d1e9d74ceed3e","repo":"decolua/9router","slug":"xai-discovery-field-is-invalid-err-message","errorCode":null,"errorMessage":"xai discovery ${field} is invalid: ${err.message}","messagePattern":"xai discovery (.+?) is invalid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/oauth/providerHelpers.js","lineNumber":8,"sourceCode":"const BASE64_BLOCK_SIZE = 4;\n\nfunction validateXaiOAuthEndpoint(rawUrl, field) {\n  const value = String(rawUrl || \"\").trim();\n  if (!value) throw new Error(`xai discovery ${field} is empty`);\n  let parsed;\n  try { parsed = new URL(value); } catch (err) {\n    throw new Error(`xai discovery ${field} is invalid: ${err.message}`);\n  }\n  if (parsed.protocol !== \"https:\") throw new Error(`xai discovery ${field} must use https: ${value}`);\n  const host = parsed.hostname.toLowerCase().trim();\n  if (host !== \"x.ai\" && !host.endsWith(\".x.ai\")) {\n    throw new Error(`xai discovery ${field} host ${host} is not on x.ai`);\n  }\n  return value;\n}\n\nfunction decodeXaiIdTokenEmail(idToken) {\n  if (!idToken || typeof idToken !== \"string\") return undefined;\n  const parts = idToken.split(\".\");\n  if (parts.length !== 3) return undefined;\n  try {\n    const base64 = parts[1].replace(/-/g, \"+\").replace(/_/g, \"/\");\n    const padding = (BASE64_BLOCK_SIZE - (base64.length % BASE64_BLOCK_SIZE)) % BASE64_BLOCK_SIZE;\n    const json = Buffer.from(base64 + \"=\".repeat(padding), \"base64\").toString(\"utf8\");\n    const payload = JSON.parse(json);","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/providerHelpers.js#L1-L26","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst tokenUrl = validateXaiOAuthEndpoint('x.ai/api/oauth/token', 'token_endpoint'); // throws: Invalid URL\n// after\nconst tokenUrl = validateXaiOAuthEndpoint('https://x.ai/api/oauth/token', 'token_endpoint');","handlingStrategy":"validation","validationCode":"function isParseableUrl(v) {\n  if (typeof v !== 'string') return false;\n  try { new URL(v.trim()); return true; } catch { return false; }\n}\n// use: isParseableUrl(data.token_endpoint) ? validateXaiOAuthEndpoint(data.token_endpoint, 'token_endpoint') : fallback","typeGuard":"function isHttpUrl(v) {\n  try { return new URL(String(v).trim()) instanceof URL; } catch { return false; }\n}","tryCatchPattern":"try {\n  const tokenUrl = validateXaiOAuthEndpoint(data.token_endpoint, 'token_endpoint');\n  // use tokenUrl\n} catch (err) {\n  if (/xai discovery .* is invalid:/.test(err.message)) {\n    console.warn('xAI discovery endpoint unparseable, using static fallback', err.message);\n    return { authorizeUrl: XAI_CONFIG.authorizeUrl, tokenUrl: XAI_CONFIG.tokenUrl };\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["oauth","xai","url-validation","discovery"],"backgroundTag":"oauth-discovery-invalid-endpoint","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}