{"record":{"id":"58a2b26092f9f8c7","repo":"DIYgod/RSSHub","slug":"build-id-not-found","errorCode":null,"errorMessage":"Build ID not found.","messagePattern":"Build ID not found\\.","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/tidb/blog.ts","lineNumber":77,"sourceCode":"                    return `<blockquote>${parseContentToHtml(node.children)}</blockquote>`;\n                default:\n                    return '';\n            }\n        })\n        .join('') ?? '';\n\nexport const handler = async (ctx: Context): Promise<Data> => {\n    const { category = 'latest' } = ctx.req.param();\n    const limit = Number(ctx.req.query('limit') ?? '20');\n\n    const baseUrl = 'https://tidb.net';\n    const targetUrl: string = new URL(`blog${category === 'latest' ? '' : `/c/${category}`}`, baseUrl).href;\n    const targetResponse = await ofetch(targetUrl);\n\n    const buildId: string | undefined = targetResponse.match(/\"buildId\":\"(.*?)\"/)?.[1];\n\n    if (!buildId) {\n        throw new Error('Build ID not found.');\n    }\n\n    const $: CheerioAPI = load(targetResponse);\n    const language = $('html').attr('lang') ?? 'zh';\n\n    const apiUrl: string = new URL(`_next/data/${buildId}/${language}/blog${category === 'latest' ? '' : `/c/${category}`}.json`, baseUrl).href;\n\n    const response = await ofetch(apiUrl, {\n        query: {\n            latest: true,\n        },\n    });\n\n    let items: DataItem[] = response.pageProps.blogs.content.slice(0, limit).map((item): DataItem => {\n        const title: string = item.title;\n        const description: string | undefined = item.summary;\n        const pubDate: number | string = item.publishedAt;\n        const linkUrl: string | undefined = item.slug ? `blog/${item.slug}` : undefined;","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/tidb/blog.ts#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-fetch https://tidb.net/blog in a browser and grep for `buildId` to confirm it still exists.","If the buildId moved, update the regex on line 75 to the new serialization.","If the site dropped Next.js data routes, switch to the new CMS/API the site exposes.","Verify baseUrl and targetUrl resolve without a redirect."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const targetResponse = await ofetch(targetUrl);\nconst buildId = targetResponse.match(/\"buildId\":\"(.*?)\"/)?.[1];\nif (!buildId) throw new Error('TiDB page no longer exposes Next.js buildId — verify site front-end');","typeGuard":"const isBuildId = (v: unknown): v is string => typeof v === 'string' && /^[A-Za-z0-9_-]+$/.test(v);","tryCatchPattern":"try { /* handler body using buildId */ }\ncatch (e) { if (e instanceof Error && /Build ID/.test(e.message)) { /* surface 503 or fall back to HTML scraping */ } else throw e; }","preventionTips":["Watch TiDB.net deploys for front-end framework changes","Add a smoke test that asserts buildId is parseable","Fall back to scraping when _next/data is unavailable"],"tags":["nextjs","scraping","buildid","tidb","html-parsing"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}