decolua/9router · info · Error
"No JSON found in decoded code"
Error message
"No JSON found in decoded code"
What it means
clinepass.js duplicates cline.js's shortcut: it treats the callback `code` as base64-encoded JSON token data, decodes it, and throws this error when the decoded text contains no '}' (no JSON object). As in cline.js, this throw deliberately transfers control to the catch block that performs the real HTTP token exchange, so it is an internal control-flow signal rather than a user-facing failure.
Source
Thrown at src/lib/oauth/providers/clinepass.js:22
config: CLINEPASS_CONFIG,
flowType: "authorization_code",
buildAuthUrl: (config, redirectUri) => {
const params = new URLSearchParams({
client_type: "extension",
callback_url: redirectUri,
redirect_uri: redirectUri,
});
return `${config.authorizeUrl}?${params.toString()}`;
},
exchangeToken: async (config, code, redirectUri) => {
try {
// Cline encodes token data as base64 in the code param
let base64 = code;
const padding = 4 - (base64.length % 4);
if (padding !== 4) base64 += "=".repeat(padding);
const decoded = Buffer.from(base64, "base64").toString("utf-8");
const lastBrace = decoded.lastIndexOf("}");
if (lastBrace === -1) throw new Error("No JSON found in decoded code");
const tokenData = JSON.parse(decoded.substring(0, lastBrace + 1));
return {
access_token: tokenData.accessToken,
refresh_token: tokenData.refreshToken,
email: tokenData.email,
firstName: tokenData.firstName,
lastName: tokenData.lastName,
expires_at: tokenData.expiresAt,
};
} catch (e) {
const response = await fetch(config.tokenUrl, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify({ grant_type: "authorization_code", code, client_type: "extension", redirect_uri: redirectUri }),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`ClinePass token exchange failed: ${error}`);View on GitHub (pinned to 90b52e06ff)
Solutions
- Usually none: the catch block falls back to the HTTP token exchange automatically.
- If the overall flow still fails, inspect the fallback exchange error (its message names the upstream cause).
- Confirm the code param is passed through unmodified from Cline's redirect.
- If the shortcut path is permanently dead upstream, remove or guard the base64 parse to avoid confusing logs.
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
function clinePassCodeHasJson(code) {
if (typeof code !== 'string' || !code) return false;
let b = code;
const pad = 4 - (b.length % 4);
if (pad !== 4) b += '='.repeat(pad);
const decoded = Buffer.from(b, 'base64').toString('utf-8');
return decoded.includes('{') && decoded.lastIndexOf('}') !== -1;
}
// route directly to the HTTP path when this returns false Type guard
function isBase64JsonObject(code) {
if (typeof code !== 'string') return false;
try {
const decoded = Buffer.from(code, 'base64').toString('utf-8');
return decoded.lastIndexOf('}') !== -1;
} catch { return false; }
} Try / catch
try {
const tokens = await clinepass.exchangeToken(config, code, redirectUri);
// use tokens
} catch (err) {
if (err.message === 'No JSON found in decoded code') {
// internal branch trigger — HTTP fallback already executed;
// seeing this thrown means the fallback also failed — inspect its error
}
throw err;
} Prevention
- Expect this throw on every plain-code flow; it is the designed handoff to the HTTP exchange.
- Match on the exact message string 'No JSON found in decoded code' if you branch on it.
- Preserve the code param verbatim from the redirect (no extra decoding/trimming).
- If the shortcut never succeeds in your environment, prefer calling the HTTP exchange directly to avoid noisy throws.
When it happens
Trigger: exchangeToken called with a plain authorization code, an empty string, or any non-base64-JSON value from the Cline Pass callback; also happens whenever Cline's current flow issues ordinary codes instead of encoded payloads.
Common situations: Cline Pass changing its callback payload format, manual testing with arbitrary code strings, double-URL-decoding corrupting the base64, or callbacks carrying error/none codes.
Related errors
- "No JSON found in decoded code"
- `Cline token exchange failed: ${error}`
- [Claude Usage] OAuth endpoint returned ${oauthResponse.statu
- [Codex Reset Credits] force refresh failed: ${retryError.mes
- [Usage] ${connection.provider}: force refresh failed: ${retr
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/40074148a60cb8b5.
Report an issue: GitHub.