decolua/9router · error
Kimchi token validation failed
Error message
Kimchi token validation failed
What it means
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.
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.
Example fix
// before: swallowing the reason and surfacing a generic message
throw new Error(check.error || "Kimchi token validation failed");
// after: log the HTTP status captured by validateToken for diagnosis
if (!check.valid) {
console.error("kimchi validate failed:", check.error, check.status);
throw new Error(check.error || "Kimchi token validation failed");
} Defensive patterns
Strategy: try-catch
Validate before calling
function looksLikeBearer(t) { return typeof t === "string" && t.length > 20 && !t.includes(" "); }
if (!looksLikeBearer(params.token)) throw new Error("Malformed Kimchi token in callback"); Type guard
function hasToken(p) { return typeof p === 'object' && p !== null && typeof p.token === 'string' && p.token.length > 0; } Try / catch
try {
const { token } = await kimchiResult;
use(token);
} catch (e) {
if (/token validation failed|isn't valid/i.test(e.message)) {
restartLogin(); // stale/invalid token — redo browser login
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ${callbackParams.error_description || callbackParams.error}
- Failed to refresh credentials. Please re-authorize the…
- GitHub authentication failed
- `Kimchi token validation failed
- No authorization code received
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/94dcdd98d1d778ed.
Report an issue: GitHub.
Appendix: source
Thrown at src/lib/oauth/services/kimchi.js:87
const authUrl = buildKimchiAuthUrl(callbackUrl, state);
return { authUrl, port, state, result, close };
}
async _handleCallback(params, expectedState) {
if (params.error) {
throw new Error(params.error_description || params.error);
}
const candidate = params.state;
if (!candidate || candidate !== expectedState) {
throw new Error("This request isn't valid. Please restart the Kimchi login flow.");
}
const token = params.token;
if (!token) {
throw new Error("No token was returned by the Kimchi authentication server");
}
const check = await this.validateToken(token);
if (!check.valid) {
throw new Error(check.error || "Kimchi token validation failed");
}
return { token };
}
async fetchProfile(token) {
try {
const res = await fetch(KIMCHI_CONFIG.meUrl, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok) return {};
const j = await res.json();
return { displayName: j.name, email: j.email, username: j.username };
} catch {
return {};
}
}
// Validate a token against Kimchi's supported-providers endpoint.View on GitHub (pinned to 90b52e06ff)