DIYgod/RSSHub · error · Error

Build ID not found.

Error message

Build ID not found.

What it means

Thrown by the TiDB blog route when the Next.js `buildId` cannot be regex-extracted from the fetched page HTML. The buildId is needed to construct the `_next/data/{buildId}/.../blog.json` API URL, so without it the route cannot proceed.

Source

Thrown at lib/routes/tidb/blog.ts:77

                    return `<blockquote>${parseContentToHtml(node.children)}</blockquote>`;
                default:
                    return '';
            }
        })
        .join('') ?? '';

export const handler = async (ctx: Context): Promise<Data> => {
    const { category = 'latest' } = ctx.req.param();
    const limit = Number(ctx.req.query('limit') ?? '20');

    const baseUrl = 'https://tidb.net';
    const targetUrl: string = new URL(`blog${category === 'latest' ? '' : `/c/${category}`}`, baseUrl).href;
    const targetResponse = await ofetch(targetUrl);

    const buildId: string | undefined = targetResponse.match(/"buildId":"(.*?)"/)?.[1];

    if (!buildId) {
        throw new Error('Build ID not found.');
    }

    const $: CheerioAPI = load(targetResponse);
    const language = $('html').attr('lang') ?? 'zh';

    const apiUrl: string = new URL(`_next/data/${buildId}/${language}/blog${category === 'latest' ? '' : `/c/${category}`}.json`, baseUrl).href;

    const response = await ofetch(apiUrl, {
        query: {
            latest: true,
        },
    });

    let items: DataItem[] = response.pageProps.blogs.content.slice(0, limit).map((item): DataItem => {
        const title: string = item.title;
        const description: string | undefined = item.summary;
        const pubDate: number | string = item.publishedAt;
        const linkUrl: string | undefined = item.slug ? `blog/${item.slug}` : undefined;

View on GitHub (pinned to bed535e087)

Solutions

  1. Re-fetch https://tidb.net/blog in a browser and grep for `buildId` to confirm it still exists.
  2. If the buildId moved, update the regex on line 75 to the new serialization.
  3. If the site dropped Next.js data routes, switch to the new CMS/API the site exposes.
  4. Verify baseUrl and targetUrl resolve without a redirect.
Defensive patterns

Strategy: validation

Validate before calling

const targetResponse = await ofetch(targetUrl);
const buildId = targetResponse.match(/"buildId":"(.*?)"/)?.[1];
if (!buildId) throw new Error('TiDB page no longer exposes Next.js buildId — verify site front-end');

Type guard

const isBuildId = (v: unknown): v is string => typeof v === 'string' && /^[A-Za-z0-9_-]+$/.test(v);

Try / catch

try { /* handler body using buildId */ }
catch (e) { if (e instanceof Error && /Build ID/.test(e.message)) { /* surface 503 or fall back to HTML scraping */ } else throw e; }

Prevention

When it happens

Trigger: ofetch(targetUrl) returns HTML that does not contain `"buildId":"..."` (line 75 regex misses), so line 78-80 throws a generic Error. Causes: site migrated off Next.js, served a static/error page, or changed the buildId serialization.

Common situations: TiDB.net deploys a non-Next.js front-end; a CDN serves a cached error page; the page requires a locale cookie and returns a redirect HTML without buildId.

Related errors


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