{"record":{"id":"d84e1aae09b654f2","repo":"DIYgod/RSSHub","slug":"api-error-response-message-d84e1a","errorCode":null,"errorMessage":"API error: ${response.message}","messagePattern":"API error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/codefather/questions.ts","lineNumber":51,"sourceCode":"    const sort = ctx.req.param('sort') || 'new';\n\n    const sortConfig = sort === 'hot' ? { field: 'favourNum', name: '热门' } : { field: 'createTime', name: '最新' };\n\n    const response = await ofetch('https://api.codefather.cn/api/qa/list/page/vo', {\n        method: 'POST',\n        headers: {\n            'Content-Type': 'application/json',\n        },\n        body: {\n            current: 1,\n            pageSize: 20,\n            sortField: sortConfig.field,\n            sortOrder: 'descend',\n        },\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 title = (item.title as string) || '无标题';\n        const content = (item.content as string) || '';\n        const user = (item.user as Record<string, unknown>) || {};\n        const tags = (item.tags as string[]) || [];\n        const bestComment = item.bestComment as Record<string, unknown> | undefined;\n\n        // Build description content\n        let description = `<div>${content.replaceAll('\\n', '<br>')}</div>`;\n\n        // Add best answer\n        if (bestComment) {\n            const answerUser = (bestComment.user as Record<string, unknown>) || {};\n            description += '<hr><h4>💡 最佳回答</h4>';","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/codefather/questions.ts#L33-L69","documentation":"Thrown by the Codefather questions route when the upstream `api.codefather.cn` questions-list endpoint returns `code !== 0`. Same envelope convention as the posts route: 0 = success, non-zero = error with `response.message`. The handler hardcodes `{ current: 1, pageSize: 20, sortField, sortOrder: 'descend' }`. Plain `Error`.","triggerScenarios":"The `sortConfig.field` value is not accepted by the API, the endpoint is temporarily degraded, or an anonymous request triggers a login-required business error code.","commonSituations":"Maintainer changed `sortConfig.field` to an unsupported value; the API tightened auth; transient backend failure.","solutions":["Read `response.message` for the API's stated reason.","Verify `sortConfig.field` against the values the codefather.cn frontend actually sends (network tab).","Retry once for transient backend errors.","If auth-related, the endpoint may now require a token the route does not provide."],"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 });\n    if (response.code !== 0) {\n        throw new Error(`API error: ${response.message}`);\n    }\n} catch (e) {\n    throw new Error(`Codefather questions failed: ${(e as Error).message}`);\n}","preventionTips":["Confirm `sortConfig.field` is in the API's accepted sortfield whitelist.","Watch for auth-required business codes after codefather.cn backend changes.","Log the full response (code + message) once when diagnosing; the message is the API's own explanation."],"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"}