{"record":{"id":"8acd1cb7599cfc03","repo":"DIYgod/RSSHub","slug":"api-error-response-message","errorCode":null,"errorMessage":"API error: ${response.message}","messagePattern":"API error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/codefather/posts.ts","lineNumber":67,"sourceCode":"        pageSize: 20,\n        sortField: sortConfig.field,\n        sortOrder: 'descend',\n    };\n\n    if (category && validCategories.has(category)) {\n        requestBody.category = category;\n    }\n\n    const response = await ofetch('https://api.codefather.cn/api/post/list/page/vo', {\n        method: 'POST',\n        headers: {\n            'Content-Type': 'application/json',\n        },\n        body: requestBody,\n    });\n\n    if (response.code !== 0) {\n        throw new Error(`API error: ${response.message}`);\n    }\n\n    const records = response.data?.records || [];\n\n    const items = records.map((item: Record<string, unknown>) => {\n        const content = (item.content as string) || '';\n        const pictureList = (item.pictureList as string[]) || [];\n        const user = (item.user as Record<string, unknown>) || {};\n        const tags = (item.tags as Array<{ tagName: string }>) || [];\n\n        // Build description content\n        let description = `<p>${content.replaceAll('\\n', '<br>')}</p>`;\n\n        // Add images\n        if (pictureList.length > 0) {\n            description += '<div>';\n            for (const pic of pictureList) {\n                description += `<img src=\"${pic}\" style=\"max-width: 100%;\" />`;","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/codefather/posts.ts#L49-L85","documentation":"Thrown by the Codefather posts route when the upstream JSON API `https://api.codefather.cn/api/post/list/page/vo` returns `code !== 0`. Codefather's convention: `code: 0` = success, any other code is an error and `response.message` carries the Chinese-language reason. The route surfaces that message verbatim. Plain `Error`.","triggerScenarios":"Posting a request body the API rejects (malformed category, invalid sorting field, missing required field), server-side validation failure, or an authenticated-only operation attempted anonymously.","commonSituations":"Passing an unknown `category` value into `requestBody.category`, sending a `sortField` not in the API's whitelist, or the API temporarily returning 5xx-mapped business codes during maintenance.","solutions":["Read the surfaced `response.message` — it is the API's own explanation (often in Chinese).","Compare the request body against a known-working call captured from codefather.cn in the browser network tab.","If `category` was supplied, confirm it is a valid category id on the site.","Retry transient business errors after a short delay."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isCodefatherSuccess(r: unknown): r is { code: 0; data: { records: unknown[] } } {\n    return typeof r === 'object' && r !== null && (r as any).code === 0;\n}","tryCatchPattern":"try {\n    const response = await ofetch(url, { method: 'POST', body: requestBody });\n    if (response.code !== 0) {\n        throw new Error(`API error: ${response.message}`);\n    }\n} catch (e) {\n    // network vs. business error\n    throw new Error(`Codefather posts failed: ${(e as Error).message}`);\n}","preventionTips":["Capture a working request body from codefather.cn's network tab and diff against the route's body.","Validate `category` against the site's real category ids before adding to `requestBody`.","Retry once on transient business codes, but treat persistent non-zero codes as an API-contract change."],"tags":["upstream-api","response-shape","external-service","api-contract"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}