{"record":{"id":"6d484720d71e3c51","repo":"jackwener/OpenCLI","slug":"label-returned-invalid-json-outcome-detail","errorCode":null,"errorMessage":"${label} returned invalid JSON: ${outcome.detail}","messagePattern":"(.+?) returned invalid JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/jike/utils.js","lineNumber":82,"sourceCode":"      let body;\n      try {\n        body = await response.json();\n      } catch (error) {\n        return { kind: 'json', status: response.status, detail: String(error?.message || error) };\n      }\n      return { kind: 'response', status: response.status, body };\n    } catch (error) {\n      return { kind: 'transport', detail: String(error?.message || error) };\n    }\n  })()`);\n  if (outcome?.kind === 'auth' || outcome?.status === 401 || outcome?.status === 403) {\n    throw new AuthRequiredError('web.okjike.com', outcome?.detail || `${label} returned HTTP ${outcome?.status}`);\n  }\n  if (outcome?.kind === 'transport') {\n    throw new CommandExecutionError(`${label} request failed: ${outcome.detail}`);\n  }\n  if (outcome?.kind === 'json') {\n    throw new CommandExecutionError(`${label} returned invalid JSON: ${outcome.detail}`);\n  }\n  if (outcome?.kind !== 'response' || !Number.isInteger(outcome.status)) {\n    throw new CommandExecutionError(`${label} returned an unexpected response`);\n  }\n  if (outcome.status < 200 || outcome.status >= 300) {\n    throw new CommandExecutionError(`${label} returned HTTP ${outcome.status}`);\n  }\n  return outcome.body;\n}\n\n/**\n * 注入浏览器 evaluate 的 JS 函数字符串。\n * 从 React fiber 树中向上最多走 10 层，找到含 id 字段的 props.data。\n */\nexport const getPostDataJs = `\nfunction getPostData(element) {\n  for (const key of Object.keys(element)) {\n    if (key.startsWith('__reactFiber$') || key.startsWith('__reactInternalInstance$')) {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jike/utils.js#L64-L100","documentation":"postJikeApi expects every successful response to be JSON. When the response body cannot be parsed as JSON (kind 'json'), it throws CommandExecutionError with the parse error detail. This guards callers from receiving undefined/garbage data when the server returns HTML (login page, error page, WAF challenge) or an empty body.","triggerScenarios":"A request to web.okjike.com returns HTTP 200 but a non-JSON body: an HTML login/redirect page, a Cloudflare/WAF challenge page, an empty body, or a truncated response, so JSON.parse fails inside the fetch wrapper.","commonSituations":"Session cookies expired and the server returns an HTML login page with 200; site placed a bot-check/verification page; server returned an error page with wrong Content-Type; CDN interception.","solutions":["Re-authenticate: run the site's auth/login flow so cookies are fresh and the server stops returning HTML pages","Check outcome.detail in the message for the exact JSON parse error and inspect the raw body","Confirm the endpoint still returns JSON (open it in a browser or with curl using the same cookies)","Disable interfering proxies/VPN or anti-bot tooling that may inject challenge pages","Retry later if it is a temporary WAF/CDN issue"],"exampleFix":"// before\nconst feed = await body('postJikeApi', '/api/feed');\n// after\nlet feed;\ntry {\n  feed = await body('postJikeApi', '/api/feed');\n} catch (err) {\n  if (/invalid JSON/.test(err.message)) {\n    throw new AuthRequiredError('web.okjike.com', 'Session likely expired — re-run login flow');\n  }\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"const res = await fetch('https://web.okjike.com/<endpoint>', { headers });\nconst text = await res.text();\ntry { JSON.parse(text); } catch { throw new Error('Endpoint returning non-JSON — re-login or check for WAF challenge'); }","typeGuard":"function isInvalidJsonError(err) {\n  return err instanceof CommandExecutionError && /invalid JSON/.test(err.message);\n}","tryCatchPattern":"try {\n  const body = await body('postJikeApi', path, payload);\n} catch (err) {\n  if (isInvalidJsonError(err)) {\n    // likely HTML login page or WAF challenge: trigger re-auth flow\n  } else throw err;\n}","preventionTips":["Keep jike session cookies fresh; re-run login periodically","Detect HTML responses early and route to the auth flow","Avoid proxies/VPN endpoints that trigger WAF challenges","Log raw response bodies when parse errors occur"],"tags":["json","http","parsing","jike"],"backgroundTag":"invalid-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}