{"record":{"id":"bf6cb3f5152020e2","repo":"jackwener/OpenCLI","slug":"probe-detail-bf6cb3","errorCode":null,"errorMessage":"${probe.detail}","messagePattern":"\\$\\{probe\\.detail\\}","errorType":"exception","errorClass":"AuthRequiredError('web.okjike.com')","httpStatus":null,"severity":"error","filePath":"clis/jike/utils.js","lineNumber":30,"sourceCode":"    const token = localStorage.getItem('JK_ACCESS_TOKEN') || '';\n    if (!token) return { kind: 'auth', detail: 'Jike JK_ACCESS_TOKEN missing from localStorage (anonymous)' };\n    const r = await fetch('https://api.ruguoapp.com/1.0/users/profile', {\n      headers: { 'x-jike-access-token': token, Accept: 'application/json' },\n    });\n    if (r.status === 401 || r.status === 403) return { kind: 'auth', detail: 'Jike users/profile HTTP ' + r.status };\n    if (!r.ok) return { kind: 'http', httpStatus: r.status };\n    const d = await r.json();\n    const u = d && d.user;\n    if (!u || !u.id) return { kind: 'auth', detail: 'Jike users/profile returned no user (anonymous)' };\n    return { ok: true, user_id: String(u.id), screen_name: String(u.screenName || ''), username: String(u.username || '') };\n  } catch (e) {\n    return { kind: 'exception', detail: String(e && e.message || e) };\n  }\n})()`;\n\nexport async function requireJikeIdentity(page) {\n  const probe = await page.evaluate(JIKE_IDENTITY_PROBE);\n  if (probe?.kind === 'auth') throw new AuthRequiredError('web.okjike.com', probe.detail);\n  if (probe?.kind === 'http') throw new CommandExecutionError(`HTTP ${probe.httpStatus} from Jike users/profile`);\n  if (probe?.kind === 'exception') throw new CommandExecutionError(`Jike identity probe failed: ${probe.detail}`);\n  if (!probe?.ok) throw new CommandExecutionError(`Unexpected Jike identity probe: ${JSON.stringify(probe)}`);\n  return { user_id: probe.user_id, screen_name: probe.screen_name, username: probe.username };\n}\n\nexport function normalizeJikeLimit(raw, defaultValue = 20) {\n  const limit = raw ?? defaultValue;\n  if (!Number.isInteger(limit) || limit < 1) {\n    throw new ArgumentError('--limit must be a positive integer');\n  }\n  return limit;\n}\n\nexport async function postJikeApi(page, path, requestBody, label) {\n  const url = `https://api.ruguoapp.com${path}`;\n  const outcome = await page.evaluate(`(async () => {\n    const token = localStorage.getItem('JK_ACCESS_TOKEN') || '';","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jike/utils.js#L12-L48","documentation":"AuthRequiredError for web.okjike.com thrown by requireJikeIdentity when the in-page identity probe reports kind 'auth': the JK_ACCESS_TOKEN is missing from localStorage, or the users/profile call returned 401/403 or no user object. The library requires a logged-in Jike session before running any identity-bound command.","triggerScenarios":"Calling verifyJikeIdentity (via requireJikeIdentity) while the browser page is logged out — no JK_ACCESS_TOKEN in localStorage, an expired token rejected with 401/403, or the profile endpoint returning no user for an anonymous session.","commonSituations":"Fresh browser profile never logged into Jike; token expired after Jike rotated sessions; cookies/localStorage cleared; running in CI where no interactive login exists.","solutions":["Log into web.okjike.com in the browser session the CLI drives, then retry","Verify localStorage JK_ACCESS_TOKEN exists on web.okjike.com; re-login if absent","If the token exists but returns 401/403, log out and back in to mint a fresh token","Persist a dedicated browser profile for the CLI so the login survives restarts"],"exampleFix":"// before: headless run with no session\nconst identity = await verifyJikeIdentity(page); // throws AuthRequiredError\n// after: ensure login first\nawait loginJike(page); // opens browser for interactive login\nconst identity = await verifyJikeIdentity(page);","handlingStrategy":"try-catch","validationCode":"const token = localStorage.getItem('JK_ACCESS_TOKEN');\nif (!token) throw new Error('Log into web.okjike.com before running identity-bound Jike commands');","typeGuard":"function isIdentity(v) {\n  return !!v && typeof v === 'object' && typeof v.user_id === 'string' && v.user_id.length > 0;\n}","tryCatchPattern":"try {\n  const identity = await verifyJikeIdentity(page);\n} catch (e) {\n  if (e.name === 'AuthRequiredError') {\n    await loginJike(page); // interactive re-login\n    return verifyJikeIdentity(page);\n  }\n  throw e;\n}","preventionTips":["Log into web.okjike.com in the browser profile the CLI uses","Persist a dedicated profile so sessions survive restarts","Re-login proactively when tokens age out","Avoid privacy modes that block localStorage"],"tags":["authentication","jike","session-expired"],"backgroundTag":"auth-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}