{"record":{"id":"70525ed91a9a8f4d","repo":"DIYgod/RSSHub","slug":"post-message","errorCode":null,"errorMessage":"${post.message}","messagePattern":"\\$\\{post\\.message\\}","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/dxy/utils.ts","lineNumber":53,"sourceCode":"};\n\nconst getPost = (item) =>\n    cache.tryGet(item.link, async () => {\n        const postParams = {\n            postId: item.postId,\n            serverTimestamp: Date.now(),\n            timestamp: Date.now(),\n            noncestr: generateNonce(8, 'number'),\n        };\n\n        const post = await ofetch<PostData>('https://www.dxy.cn/bbs/newweb/post/detail', {\n            query: {\n                ...postParams,\n                sign: sign(postParams),\n            },\n        });\n        if (post.code !== 'success') {\n            throw new Error(post.message);\n        }\n\n        const $ = load(post.data.body, null, false);\n\n        $('img').each((_, img) => {\n            const $img = $(img);\n            if ($img.data('hsrc')) {\n                $img.attr('src', $img.data('hsrc') as string);\n                $img.removeAttr('data-hsrc');\n            }\n            if ($img.data('osrc')) {\n                $img.attr('src', $img.data('osrc') as string);\n                $img.removeAttr('data-osrc');\n            }\n        });\n\n        item.description = $.html();\n        item.pubDate = parseDate(post.data.createTime, 'x');","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/dxy/utils.ts#L35-L71","documentation":"Thrown by the DXY `getPost` utility when the post detail API at `https://www.dxy.cn/bbs/newweb/post/detail` returns a non-success code. Like error 200, the request is signed with SHA1 over sorted params plus `APP_SIGN_KEY`, and the upstream `message` is rethrown verbatim. This function is shared across all dxy routes that fetch individual post bodies.","triggerScenarios":"A postId passed to getPost has been deleted, hidden, or never existed. The signing parameters (serverTimestamp, timestamp, noncestr) are rejected because the APP_SIGN_KEY is stale. DXY anti-crawler measures block the request pattern. A post requires authentication that the unsigned request lacks.","commonSituations":"A cached post link from a special-board listing points to a post that was later removed. The APP_SIGN_KEY changed after a DXY app update, breaking all post-detail fetches. Rate-limiting after batch-fetching many posts via Promise.all.","solutions":["Confirm the postId is live by opening `https://www.dxy.cn/bbs/newweb/pc/post/<id>` in a browser.","Verify `APP_SIGN_KEY` in lib/routes/dxy/utils.ts matches the current DXY app build.","If only some posts fail in a batch, wrap getPost consumers to skip errored items instead of failing the entire feed.","Log the full response to read the exact upstream message and code."],"exampleFix":"// before\nif (post.code !== 'success') {\n    throw new Error(post.message);\n}\n\n// after — include postId and code for diagnosis\nif (post.code !== 'success') {\n    throw new Error(`DXY post detail error (postId=${item.postId}, code=${post.code}): ${post.message}`);\n}","handlingStrategy":"try-catch","validationCode":"// Validate postId is numeric before calling getPost\nfunction isValidPostId(id: unknown): boolean {\n    return typeof id === 'string' && /^\\d+$/.test(id);\n}","typeGuard":"// Type guard for the DXY post detail success response\nfunction isDxyPostSuccess(res: unknown): res is { code: 'success'; data: PostData } {\n    return typeof res === 'object' && res !== null &&\n        (res as any).code === 'success';\n}","tryCatchPattern":"// When mapping over posts, catch individual failures to avoid failing the entire feed\nconst items = await Promise.allSettled(list.map((item) => getPost(item)));\nconst successful = items\n    .filter((r): r is PromiseFulfilledResult<any> => r.status === 'fulfilled')\n    .map((r) => r.value);\nif (successful.length === 0) {\n    throw new Error('All post fetches failed');\n}","preventionTips":["Use Promise.allSettled instead of Promise.all when fetching multiple posts so one failure doesn't break the feed.","Keep APP_SIGN_KEY updated with the current DXY app version.","Cache post results to reduce repeated API calls for deleted posts.","Log the postId and upstream message together for faster debugging."],"tags":["api-passthrough","upstream-signing","anti-crawler","dxy","shared-utility"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}