DIYgod/RSSHub · error · Error

${post.message}

Error message

${post.message}

What it means

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.

Source

Thrown at lib/routes/dxy/utils.ts:53

};

const getPost = (item) =>
    cache.tryGet(item.link, async () => {
        const postParams = {
            postId: item.postId,
            serverTimestamp: Date.now(),
            timestamp: Date.now(),
            noncestr: generateNonce(8, 'number'),
        };

        const post = await ofetch<PostData>('https://www.dxy.cn/bbs/newweb/post/detail', {
            query: {
                ...postParams,
                sign: sign(postParams),
            },
        });
        if (post.code !== 'success') {
            throw new Error(post.message);
        }

        const $ = load(post.data.body, null, false);

        $('img').each((_, img) => {
            const $img = $(img);
            if ($img.data('hsrc')) {
                $img.attr('src', $img.data('hsrc') as string);
                $img.removeAttr('data-hsrc');
            }
            if ($img.data('osrc')) {
                $img.attr('src', $img.data('osrc') as string);
                $img.removeAttr('data-osrc');
            }
        });

        item.description = $.html();
        item.pubDate = parseDate(post.data.createTime, 'x');

View on GitHub (pinned to bed535e087)

Solutions

  1. Confirm the postId is live by opening `https://www.dxy.cn/bbs/newweb/pc/post/<id>` in a browser.
  2. Verify `APP_SIGN_KEY` in lib/routes/dxy/utils.ts matches the current DXY app build.
  3. If only some posts fail in a batch, wrap getPost consumers to skip errored items instead of failing the entire feed.
  4. Log the full response to read the exact upstream message and code.

Example fix

// before
if (post.code !== 'success') {
    throw new Error(post.message);
}

// after — include postId and code for diagnosis
if (post.code !== 'success') {
    throw new Error(`DXY post detail error (postId=${item.postId}, code=${post.code}): ${post.message}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate postId is numeric before calling getPost
function isValidPostId(id: unknown): boolean {
    return typeof id === 'string' && /^\d+$/.test(id);
}

Type guard

// Type guard for the DXY post detail success response
function isDxyPostSuccess(res: unknown): res is { code: 'success'; data: PostData } {
    return typeof res === 'object' && res !== null &&
        (res as any).code === 'success';
}

Try / catch

// When mapping over posts, catch individual failures to avoid failing the entire feed
const items = await Promise.allSettled(list.map((item) => getPost(item)));
const successful = items
    .filter((r): r is PromiseFulfilledResult<any> => r.status === 'fulfilled')
    .map((r) => r.value);
if (successful.length === 0) {
    throw new Error('All post fetches failed');
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/70525ed91a9a8f4d. Report an issue: GitHub.