decolua/9router · error
CLIProxyAPI auth JSON is invalid
Error message
CLIProxyAPI auth JSON is invalid
What it means
normalizeKiroExternalIdpAuth accepts either an object or a JSON string for the Kiro CLIProxyAPI auth. When a string is passed, JSON.parse must succeed; a parse failure means the auth blob is malformed and this error is thrown. The importer cannot proceed without a parseable auth document.
Source
Thrown at src/lib/oauth/kiroExternalIdp.js:83
if (Number.isFinite(expiresIn) && expiresIn > 0) {
return new Date(Date.now() + expiresIn * 1000).toISOString();
}
const payload = decodeJwtPayload(input.access_token || input.accessToken);
if (payload?.exp) {
return new Date(payload.exp * 1000).toISOString();
}
return new Date(Date.now() + DEFAULT_EXPIRES_IN * 1000).toISOString();
}
export function normalizeKiroExternalIdpAuth(rawAuth) {
let input = rawAuth;
if (typeof input === "string") {
try {
input = JSON.parse(input);
} catch {
throw new Error("CLIProxyAPI auth JSON is invalid");
}
}
if (!input || typeof input !== "object") {
throw new Error("CLIProxyAPI auth JSON is required");
}
const authMethod = normalizeString(input.auth_method || input.authMethod);
if (authMethod && authMethod !== "external_idp") {
throw new Error("Only external_idp Kiro auth is supported by this importer");
}
const accessToken = normalizeString(input.access_token || input.accessToken);
const refreshToken = normalizeString(input.refresh_token || input.refreshToken);
const clientId = normalizeString(input.client_id || input.clientId);
const tokenEndpoint = validateMicrosoftTokenEndpoint(input.token_endpoint || input.tokenEndpoint);
const profileArn = normalizeString(input.profile_arn || input.profileArn);
const region = normalizeString(input.region) || DEFAULT_REGION;View on GitHub (pinned to 90b52e06ff)
Solutions
- Validate the string with JSON.parse locally before calling, and print JSON.parse(err).message to see the exact syntax error position
- Re-export or re-copy the CLIProxyAPI auth file and confirm it starts with '{' and is complete
- If the value came from a file read, strip a UTF-8 BOM and read as UTF-8 before parsing
- If you actually hold a non-JSON token, wrap it in the expected auth object shape and pass the object instead of a string
Example fix
// before normalizeKiroExternalIdpAuth(fs.readFileSync(authPath, 'utf8')) // after const raw = fs.readFileSync(authPath, 'utf8').replace(/^\uFEFF/, '').trim(); const auth = JSON.parse(raw); // throws a precise SyntaxError if malformed normalizeKiroExternalIdpAuth(auth);
Defensive patterns
Strategy: validation
Validate before calling
function safeParseAuthJson(raw) {
if (typeof raw !== 'string') return raw;
try { return JSON.parse(raw.replace(/^\uFEFF/, '').trim()); }
catch (e) { throw new Error(`Kiro auth JSON parse failed: ${e.message}`); }
}
const input = safeParseAuthJson(rawAuth); Type guard
function isParseableObject(v) {
if (typeof v !== 'string') return v !== null && typeof v === 'object';
try { return JSON.parse(v) !== null && typeof JSON.parse(v) === 'object'; } catch { return false; }
} Try / catch
try {
normalizeKiroExternalIdpAuth(rawAuth);
} catch (e) {
if (e.message === 'CLIProxyAPI auth JSON is invalid') {
console.error('Auth file is not valid JSON; re-export it from CLIProxyAPI');
}
throw e;
} Prevention
- Always JSON.parse with a labeled error before handing a string to the importer
- Strip BOM and trim whitespace from file reads
- Never paste tokens/JWTs where the full auth JSON is expected
- Validate the auth file with a JSON linter after editing it by hand
When it happens
Trigger: Calling normalizeKiroExternalIdpAuth(rawAuth) with a string argument that is not valid JSON — e.g. truncated file contents, single-quoted keys, trailing commas, a raw JWT pasted instead of the auth JSON, or a file read that returned garbage/BOM-prefixed text.
Common situations: Pasting the content of a CLIProxyAPI auth file with copy/paste truncation; importing an auth file edited by hand and left syntactically invalid; passing a token string instead of the full auth JSON; reading the file with the wrong encoding (UTF-16) so the parser sees stray bytes.
Related errors
- Input must be a JSON object or array of objects
- Invalid host:port:user:pass format
- Unsupported format
- CLIProxyAPI auth JSON is required
- Invalid JSON body
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/f19228b005c8391f.
Report an issue: GitHub.