{"record":{"id":"e102533ae3264250","repo":"DIYgod/RSSHub","slug":"statusmessage","errorCode":null,"errorMessage":"${statusMessage}","messagePattern":"\\$\\{statusMessage\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/ke/results.ts","lineNumber":44,"sourceCode":"    url: 'www.research.ke.com/researchResults',\n};\n\nasync function handler() {\n    const response = await got({\n        method: 'post',\n        url: 'https://research.ke.com/apis/consumer-access/index/contents/page',\n        headers: {\n            Referer: 'https://research.ke.com/ResearchResults',\n        },\n        json: {\n            pageIndex: 1,\n            pageSize: 9,\n        },\n    });\n\n    const { status, statusMessage, data } = response;\n    if (status !== 200) {\n        throw new Error(statusMessage);\n    }\n\n    const { list } = data.data;\n\n    return {\n        title: '房地产行业研究报告',\n        link: 'https://research.ke.com/ResearchResults',\n        description: '研究成果',\n        item: list.map((item) => ({\n            title: item.title,\n            link: `https://research.ke.com/${item.contentTypeId}/ArticleDetail?id=${item.id}`,\n            author: item.author,\n            description: item.guideReading,\n            pubDate: parseDate(item.publishTime),\n        })),\n    };\n}\n","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/ke/results.ts#L26-L62","documentation":"Thrown by the ke.com (贝壳) research-results handler when the response body's `status` field (a business-level code in the JSON envelope, not the HTTP status) is not 200. The handler destructures {status, statusMessage, data} from got's response.data and re-throws statusMessage as a plain Error. Because got already threw on transport errors, reaching this line means HTTP succeeded but the application envelope reported failure.","triggerScenarios":"POST to https://research.ke.com/apis/consumer-access/index/contents/page with {pageIndex:1, pageSize:9} returns 200 OK but a JSON body whose `status` is e.g. 500, 403, or a business error code, with `statusMessage` describing it.","commonSituations":"贝克 research API rate-limiting or under maintenance; anti-crawler returning a business-level denial; upstream schema change where status is no longer the success indicator; temporary backend 5xx surfacing in the envelope.","solutions":["Retry after a short delay — many statusMessage failures are transient","Verify the endpoint and payload still match by calling the POST manually with the same JSON body","If 贝克 changed the success contract, update the status!==200 check in lib/routes/ke/results.ts:43","Surface the status code alongside the message so transient vs permanent failures are distinguishable"],"exampleFix":"// before\nif (status !== 200) {\n    throw new Error(statusMessage);\n}\n// after\nif (status !== 200) {\n    throw new Error(`ke.com research API failed: status=${status}, message=${statusMessage}`);\n}","handlingStrategy":"retry","validationCode":"async function fetchKeResults(maxRetries = 2): Promise<Data> {\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    const resp = await got({ method: 'post', url: 'https://research.ke.com/apis/consumer-access/index/contents/page', json: { pageIndex: 1, pageSize: 9 } });\n    if (resp.status === 200 && resp.data?.status === 200) return buildData(resp.data.data.list);\n    if (attempt === maxRetries) throw new Error(`ke API status=${resp.data?.status}: ${resp.data?.statusMessage}`);\n    await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));\n  }\n  throw new Error('unreachable');\n}","typeGuard":"interface KeEnvelope { status: number; statusMessage?: string; data?: { data?: { list?: unknown[] } } }\nfunction isKeSuccess(v: unknown): v is KeEnvelope {\n  return typeof v === 'object' && v !== null && (v as KeEnvelope).status === 200;\n}","tryCatchPattern":"try { return await handler(); }\ncatch (e) {\n  if (e instanceof Error && /statusMessage|ke API/i.test(e.message)) {\n    // business-level failure — retry with backoff, then degrade gracefully\n    await new Promise((r) => setTimeout(r, 2000));\n    return await handler();\n  }\n  throw e;\n}","preventionTips":["Distinguish transport status (HTTP) from envelope status (body) in logs","Retry transient envelope errors with exponential backoff","Monitor the ke research endpoint for schema changes","Surface both the code and message in thrown errors"],"tags":["api-response","network","transient"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}