{"record":{"id":"8c40fa667d568b9b","repo":"jackwener/OpenCLI","slug":"unexpected-kimi-probe-json-stringify-result","errorCode":null,"errorMessage":"Unexpected Kimi probe: ${JSON.stringify(result)}","messagePattern":"Unexpected Kimi probe: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"warning","filePath":"clis/kimi/auth.js","lineNumber":40,"sourceCode":"      const token = ${JSON.stringify(token)};\n      const res = await fetch('/api/user', { credentials: 'include', headers: { 'Authorization': 'Bearer ' + token, 'Accept': 'application/json' } });\n      if (res.status === 401 || res.status === 403) {\n        return { kind: 'auth', detail: 'Kimi /api/user HTTP ' + res.status };\n      }\n      if (!res.ok) return { kind: 'http', httpStatus: res.status };\n      const d = await res.json();\n      if (!d || !d.id) {\n        return { kind: 'auth', detail: 'Kimi /api/user returned no id — anonymous' };\n      }\n      return { ok: true, user_id: String(d.id), name: String(d.name || '') };\n    } catch (e) {\n      return { kind: 'exception', detail: String(e && e.message || e) };\n    }\n  })()`);\n  if (result?.kind === 'auth') throw new AuthRequiredError('kimi.com', result.detail);\n  if (result?.kind === 'http') throw new CommandExecutionError(`HTTP ${result.httpStatus} from /api/user`);\n  if (result?.kind === 'exception') throw new CommandExecutionError(`Kimi whoami failed: ${result.detail}`);\n  if (!result?.ok) throw new CommandExecutionError(`Unexpected Kimi probe: ${JSON.stringify(result)}`);\n  return { user_id: result.user_id, name: result.name };\n}\n\nregisterSiteAuthCommands({\n  site: 'kimi',\n  domain: 'kimi.com',\n  loginUrl: 'https://www.kimi.com/',\n  columns: ['user_id', 'name'],\n  quickCheck: hasKimiSessionCookie,\n  verify: verifyKimiIdentity,\n  poll: async (page) => {\n    if (!await hasKimiSessionCookie(page)) {\n      throw new AuthRequiredError('kimi.com', 'Waiting for Kimi auth cookies');\n    }\n    return verifyKimiIdentity(page);\n  },\n});\n","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/kimi/auth.js#L22-L58","documentation":"After checking auth/http/exception outcomes, verifyKimiIdentity requires the probe result to have `ok:true`. Any other shape (null/undefined result, or an object without ok) triggers a defensive CommandExecutionError embedding the raw probe JSON. This guards against unexpected contract changes in the in-page probe or Kimi's API response.","triggerScenarios":"The evaluated probe returns undefined (evaluate failed silently or returned non-serializable value), or returns an object that is neither ok/auth/http/exception — e.g. Kimi /api/user returns a body the probe does not map to ok:true.","commonSituations":"Kimi changed /api/user response shape (renamed `id`/`name` fields); page.evaluate returned undefined because the async IIFE failed to serialize; an intermediate proxy rewrote the response; a bug after editing the probe script.","solutions":["Inspect the JSON in the message to see the actual probe result shape","Load kimi.com and inspect /api/user manually to see the new response format","Update the probe in clis/kimi/auth.js to map the new response shape to {ok:true,user_id,name}","Re-run the whoami/verify command after fixing the probe"],"exampleFix":"// before\nif (!result?.ok) throw new CommandExecutionError(`Unexpected Kimi probe: ${JSON.stringify(result)}`);\n// after\nif (!result) throw new CommandExecutionError('Kimi probe returned no result — check page.evaluate serialization');\nif (!result.ok && result.id) return { user_id: String(result.id), name: String(result.name || '') }; // tolerate new shape\nif (!result?.ok) throw new CommandExecutionError(`Unexpected Kimi probe: ${JSON.stringify(result)}`);","handlingStrategy":"validation","validationCode":"const raw = await page.evaluate(`fetch('/api/user').then(r => r.text())`);\nlet body; try { body = JSON.parse(raw); } catch { body = null; }\nif (!body || body.id === undefined) console.warn('Unexpected /api/user shape:', raw.slice(0, 200));","typeGuard":"function isKimiUserPayload(d) {\n  return !!d && typeof d === 'object' && (typeof d.id === 'string' || typeof d.id === 'number');\n}","tryCatchPattern":"try {\n  const user = await kimiWhoami();\n} catch (e) {\n  if (/Unexpected Kimi probe/.test(e.message)) {\n    console.error('Contract drift — inspect payload:', e.message);\n    // fall back to manual login check\n  } else throw e;\n}","preventionTips":["Log the raw probe JSON on failure for diagnosis","Pin/monitor Kimi API response shape in a smoke test","Handle both string and numeric id fields in parsing code"],"tags":["kimi","contract-change","defensive","api"],"backgroundTag":"api-response-shape-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}