{"record":{"id":"672c2f171f52c7d3","repo":"jackwener/OpenCLI","slug":"label-returned-http-outcome-status","errorCode":null,"errorMessage":"${label} returned HTTP ${outcome.status}","messagePattern":"(.+?) returned HTTP (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/jike/utils.js","lineNumber":88,"sourceCode":"      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$')) {\n      let fiber = element[key];\n      for (let i = 0; i < 10 && fiber; i++) {\n        const props = fiber.memoizedProps || fiber.pendingProps;\n        if (props && props.data && props.data.id) return props.data;\n        fiber = fiber.return;\n      }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jike/utils.js#L70-L106","documentation":"postJikeApi treats any HTTP status outside 2xx as an API error and throws CommandExecutionError labeled 'X returned HTTP <status>'. Non-2xx statuses that are clearly auth failures (401/403) are handled earlier as AuthRequiredError, so this branch is for other failures like 404, 429, 5xx.","triggerScenarios":"web.okjike.com returns e.g. 400 (bad request body), 404 (endpoint renamed), 429 (rate limited) or 5xx (server error) for a jike API call routed through postJikeApi.","commonSituations":"Hitting the API too frequently (429); jike server outage (5xx); endpoint changed after a site update (404); malformed payload/params (400).","solutions":["Read the status in the message: 429 → back off and retry with delay; 5xx → retry later; 404 → check the endpoint path","For 400, verify the request payload/params your code passes to the helper","Reduce call frequency or add rate limiting between consecutive API calls","Check jike service status / community reports if 5xx persists","Update the CLI if the API surface has changed"],"exampleFix":"// before\nconst feed = await body('postJikeApi', '/api/feed');\n// after\nlet feed;\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try { feed = await body('postJikeApi', '/api/feed'); break; }\n  catch (err) {\n    if (/HTTP 429|HTTP 5\\d\\d/.test(err.message) && attempt < 2) { await sleep(3000 * (attempt + 1)); continue; }\n    throw err;\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isHttpStatusError(err, min = 400) {\n  const m = err instanceof CommandExecutionError && err.message.match(/returned HTTP (\\d{3})/);\n  return m ? Number(m[1]) >= min : false;\n}","tryCatchPattern":"try {\n  const body = await body('postJikeApi', path, payload);\n} catch (err) {\n  const m = err.message.match(/returned HTTP (\\d{3})/);\n  if (m && (m[1] === '429' || m[1].startsWith('5'))) {\n    await sleep(3000); // retry once for rate-limit/server errors\n  } else throw err;\n}","preventionTips":["Throttle request rate to avoid 429s","Distinguish 4xx (fix request) from 5xx/429 (retry) in handlers","Keep endpoint paths updated after site changes","Add jittered backoff for retries"],"tags":["http","http-status","rate-limit","jike"],"backgroundTag":"http-error-status","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}