{"record":{"id":"f19228b005c8391f","repo":"decolua/9router","slug":"cliproxyapi-auth-json-is-invalid","errorCode":null,"errorMessage":"CLIProxyAPI auth JSON is invalid","messagePattern":"CLIProxyAPI auth JSON is invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lib/oauth/kiroExternalIdp.js","lineNumber":83,"sourceCode":"  if (Number.isFinite(expiresIn) && expiresIn > 0) {\n    return new Date(Date.now() + expiresIn * 1000).toISOString();\n  }\n\n  const payload = decodeJwtPayload(input.access_token || input.accessToken);\n  if (payload?.exp) {\n    return new Date(payload.exp * 1000).toISOString();\n  }\n\n  return new Date(Date.now() + DEFAULT_EXPIRES_IN * 1000).toISOString();\n}\n\nexport function normalizeKiroExternalIdpAuth(rawAuth) {\n  let input = rawAuth;\n  if (typeof input === \"string\") {\n    try {\n      input = JSON.parse(input);\n    } catch {\n      throw new Error(\"CLIProxyAPI auth JSON is invalid\");\n    }\n  }\n\n  if (!input || typeof input !== \"object\") {\n    throw new Error(\"CLIProxyAPI auth JSON is required\");\n  }\n\n  const authMethod = normalizeString(input.auth_method || input.authMethod);\n  if (authMethod && authMethod !== \"external_idp\") {\n    throw new Error(\"Only external_idp Kiro auth is supported by this importer\");\n  }\n\n  const accessToken = normalizeString(input.access_token || input.accessToken);\n  const refreshToken = normalizeString(input.refresh_token || input.refreshToken);\n  const clientId = normalizeString(input.client_id || input.clientId);\n  const tokenEndpoint = validateMicrosoftTokenEndpoint(input.token_endpoint || input.tokenEndpoint);\n  const profileArn = normalizeString(input.profile_arn || input.profileArn);\n  const region = normalizeString(input.region) || DEFAULT_REGION;","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/kiroExternalIdp.js#L65-L101","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nnormalizeKiroExternalIdpAuth(fs.readFileSync(authPath, 'utf8'))\n// after\nconst raw = fs.readFileSync(authPath, 'utf8').replace(/^\\uFEFF/, '').trim();\nconst auth = JSON.parse(raw); // throws a precise SyntaxError if malformed\nnormalizeKiroExternalIdpAuth(auth);","handlingStrategy":"validation","validationCode":"function safeParseAuthJson(raw) {\n  if (typeof raw !== 'string') return raw;\n  try { return JSON.parse(raw.replace(/^\\uFEFF/, '').trim()); }\n  catch (e) { throw new Error(`Kiro auth JSON parse failed: ${e.message}`); }\n}\nconst input = safeParseAuthJson(rawAuth);","typeGuard":"function isParseableObject(v) {\n  if (typeof v !== 'string') return v !== null && typeof v === 'object';\n  try { return JSON.parse(v) !== null && typeof JSON.parse(v) === 'object'; } catch { return false; }\n}","tryCatchPattern":"try {\n  normalizeKiroExternalIdpAuth(rawAuth);\n} catch (e) {\n  if (e.message === 'CLIProxyAPI auth JSON is invalid') {\n    console.error('Auth file is not valid JSON; re-export it from CLIProxyAPI');\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["json","parsing","validation","oauth-import"],"backgroundTag":"invalid-json","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}