{"record":{"id":"1f98ba525dca62bb","repo":"decolua/9router","slug":"cliproxyapi-auth-json-is-required","errorCode":null,"errorMessage":"CLIProxyAPI auth JSON is required","messagePattern":"CLIProxyAPI auth JSON is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lib/oauth/kiroExternalIdp.js","lineNumber":88,"sourceCode":"  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;\n  const scope = normalizeScope(input.scopes || input.scope);\n\n  if (!accessToken) throw new Error(\"access_token is required\");\n  if (!refreshToken) throw new Error(\"refresh_token is required\");\n  if (!clientId) throw new Error(\"client_id is required\");","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/kiroExternalIdp.js#L70-L106","documentation":"After optional JSON parsing, normalizeKiroExternalIdpAuth requires the input to be a non-null object. Null, arrays of nothing meaningful, numbers, booleans, or JSON strings like '\"token\"' or 'null' reach this guard and throw. It signals the auth value was parseable but not the expected object-shaped auth document.","triggerScenarios":"Passing null/undefined, a JSON string that parses to a non-object (e.g. '\"abc\"', '123', 'null'), or an array to normalizeKiroExternalIdpAuth.","commonSituations":"A config field left empty and trimmed to empty/\"null\" text; the auth JSON file containing just a token value; a caller passing an access-token string directly instead of the full auth record.","solutions":["Pass the full CLIProxyAPI auth object containing access_token, refresh_token, client_id, token_endpoint, scopes, profile_arn","Check the source file: if it holds only a token, export the complete auth JSON instead","Add a typeof check before calling to fail with a clearer local message","If the value may be absent, guard the call site and skip import rather than passing null"],"exampleFix":"// before\nnormalizeKiroExternalIdpAuth(null)\n// after\nif (!auth || typeof auth !== 'object' || Array.isArray(auth)) {\n  throw new Error('Kiro auth file must contain a JSON object');\n}\nnormalizeKiroExternalIdpAuth(auth);","handlingStrategy":"type-guard","validationCode":"if (auth == null || typeof auth !== 'object' || Array.isArray(auth)) {\n  throw new Error('Kiro auth must be a JSON object');\n}","typeGuard":"function isAuthObject(v) {\n  return v !== null && typeof v === 'object' && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  normalizeKiroExternalIdpAuth(maybeAuth);\n} catch (e) {\n  if (e.message === 'CLIProxyAPI auth JSON is required') {\n    console.error('Auth value parsed to a non-object; check the file contents');\n  }\n  throw e;\n}","preventionTips":["Type-check the parsed value before calling the importer","Reject arrays and null explicitly, since JSON 'null' parses to null","Fail fast at config-load time with your own message rather than deep in the import","Keep auth files as complete objects — never store bare token strings in them"],"tags":["validation","oauth-import","null","shape"],"backgroundTag":"schema-validation-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}