{"record":{"id":"94dcdd98d1d778ed","repo":"decolua/9router","slug":"kimchi-token-validation-failed","errorCode":null,"errorMessage":"Kimchi token validation failed","messagePattern":"Kimchi token validation failed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lib/oauth/services/kimchi.js","lineNumber":87,"sourceCode":"    const authUrl = buildKimchiAuthUrl(callbackUrl, state);\n    return { authUrl, port, state, result, close };\n  }\n\n  async _handleCallback(params, expectedState) {\n    if (params.error) {\n      throw new Error(params.error_description || params.error);\n    }\n    const candidate = params.state;\n    if (!candidate || candidate !== expectedState) {\n      throw new Error(\"This request isn't valid. Please restart the Kimchi login flow.\");\n    }\n    const token = params.token;\n    if (!token) {\n      throw new Error(\"No token was returned by the Kimchi authentication server\");\n    }\n    const check = await this.validateToken(token);\n    if (!check.valid) {\n      throw new Error(check.error || \"Kimchi token validation failed\");\n    }\n    return { token };\n  }\n\n  async fetchProfile(token) {\n    try {\n      const res = await fetch(KIMCHI_CONFIG.meUrl, {\n        headers: { Authorization: `Bearer ${token}` },\n      });\n      if (!res.ok) return {};\n      const j = await res.json();\n      return { displayName: j.name, email: j.email, username: j.username };\n    } catch {\n      return {};\n    }\n  }\n\n  // Validate a token against Kimchi's supported-providers endpoint.","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/services/kimchi.js#L69-L105","documentation":"This error is thrown by KimchiService._handleCallback when the token returned by the Kimchi browser-login callback fails validateToken(). That validation calls Kimchi's supported-providers endpoint with the token as a Bearer; a 401/403 marks the token invalid and its error text (or this generic fallback) is thrown. It means the login completed but the resulting credential is not usable.","triggerScenarios":"A browser callback arrives at the local loopback server with a `token` query parameter, state matches, but validateToken(token) returns { valid:false } — i.e. Kimchi's API answered 401/403 for that Bearer token, or returned an explicit error message.","commonSituations":"The Kimchi auth server issued a token that was revoked or expired before the callback landed; a proxy or MITM replaced the query string; the account was disabled server-side between login and validation; clock/region issues cause the provider endpoint to reject the session.","solutions":["Restart the Kimchi browser login from scratch (startLogin) and complete it promptly — the token is validated right after issuance, so a fresh one usually passes.","Check check.error in the flow: the thrown message is the upstream error text, which usually names the real cause (401 vs 403).","Verify network access to Kimchi's validation endpoint and that no proxy strips the Authorization header.","If it reproduces for every login, confirm the account is active and not rate-limited/disabled on the Kimchi side."],"exampleFix":"// before: swallowing the reason and surfacing a generic message\nthrow new Error(check.error || \"Kimchi token validation failed\");\n// after: log the HTTP status captured by validateToken for diagnosis\nif (!check.valid) {\n  console.error(\"kimchi validate failed:\", check.error, check.status);\n  throw new Error(check.error || \"Kimchi token validation failed\");\n}","handlingStrategy":"try-catch","validationCode":"function looksLikeBearer(t) { return typeof t === \"string\" && t.length > 20 && !t.includes(\" \"); }\nif (!looksLikeBearer(params.token)) throw new Error(\"Malformed Kimchi token in callback\");","typeGuard":"function hasToken(p) { return typeof p === 'object' && p !== null && typeof p.token === 'string' && p.token.length > 0; }","tryCatchPattern":"try {\n  const { token } = await kimchiResult;\n  use(token);\n} catch (e) {\n  if (/token validation failed|isn't valid/i.test(e.message)) {\n    restartLogin(); // stale/invalid token — redo browser login\n  } else throw e;\n}","preventionTips":["Complete the browser login promptly — don't let the callback sit past the 5-minute session TTL or the callback timeout.","Surface check.error to the user instead of a generic message so 401 vs 403 is distinguishable.","Treat any validation failure as 'retry the login', never 'retry the request with the same token'.","Never cache or persist a Kimchi token before validateToken passes."],"tags":["oauth","authentication","token-validation","browser-login"],"backgroundTag":"oauth-callback-invalid-token","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}