{"record":{"id":"8ff5081dfdc2afe2","repo":"decolua/9router","slug":"xai-discovery-field-is-invalid-err-message-8ff508","errorCode":null,"errorMessage":"xai discovery ${field} is invalid: ${err.message}","messagePattern":"xai discovery (.+?) is invalid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/xai.js","lineNumber":34,"sourceCode":" *  2. Bind loopback server on 127.0.0.1:56121, path /callback\n *  3. PKCE S256 with 96-byte verifier\n *  4. Exchange code with form-urlencoded body\n *  5. id_token email decode (no signature verify, mirrors Go)\n */\n\nconst BASE64_BLOCK_SIZE = 4;\n\nlet cachedDiscovery = null;\n\nexport function validateOAuthEndpoint(rawUrl, field) {\n  const value = String(rawUrl || \"\").trim();\n  if (!value) throw new Error(`xai discovery ${field} is empty`);\n\n  let parsed;\n  try {\n    parsed = new URL(value);\n  } catch (err) {\n    throw new Error(`xai discovery ${field} is invalid: ${err.message}`);\n  }\n\n  if (parsed.protocol !== \"https:\") {\n    throw new Error(`xai discovery ${field} must use https: ${value}`);\n  }\n\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\n  return value;\n}\n\n/**\n * Discover authorization + token endpoints. Cached process-wide.\n */\nexport async function discoverEndpoints() {","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/xai.js#L16-L52","documentation":"Thrown when a discovery URL field is non-empty but cannot be parsed by the URL constructor. The underlying URL parser message is embedded, e.g. 'Invalid URL'. This guarantees downstream code only works with structurally valid absolute URLs.","triggerScenarios":"Field contains a relative path ('/oauth/token'), a placeholder ('your-auth-url-here'), or a malformed string (missing scheme, stray spaces mid-URL, typo like 'https//x.ai').","commonSituations":"Hand-edited env values with typos; copy-pasting URLs with trailing control characters; template placeholders left un-substituted in config files.","solutions":["Read the embedded err.message and the field name to locate the malformed value.","Ensure the value is a full absolute URL including https:// scheme.","Trim whitespace/newlines copied into env or config values.","Run new URL(value) yourself in a REPL to reproduce the parser complaint before fixing."],"exampleFix":"// before\nXAI_TOKEN_URL=/api/oauth/token\n// after\nXAI_TOKEN_URL=https://x.ai/api/oauth/token","handlingStrategy":"validation","validationCode":"function isParsableUrl(u) {\n  try { new URL(String(u || '').trim()); return true; } catch { return false; }\n}\nif (!isParsableUrl(cfg.tokenUrl)) throw new Error(`xAI tokenUrl not a valid absolute URL: ${cfg.tokenUrl}`);","typeGuard":"function isValidUrl(u) {\n  if (typeof u !== 'string') return false;\n  try { new URL(u.trim()); return true; } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Always store fully-qualified absolute URLs (with https://) in env/config.","Trim whitespace and strip quotes when reading values from .env files.","Sanity-check URLs with new URL() at config-load time."],"tags":["oauth","xai","url","validation"],"backgroundTag":"invalid-url","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}