{"record":{"id":"8e3fc4d13b9a548e","repo":"DIYgod/RSSHub","slug":"missing-next-data","errorCode":null,"errorMessage":"missing next data","messagePattern":"missing next data","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/leagueoflegends/patch-notes.ts","lineNumber":30,"sourceCode":"        {\n            source: ['www.leagueoflegends.com/en-us/news/tags/patch-notes/', 'www.leagueoflegends.com/en-us/news/game-updates/:postSlug'],\n        },\n    ],\n    name: 'Patch Notes',\n    maintainers: ['noahm'],\n    async handler() {\n        const url = 'https://www.leagueoflegends.com/en-us/news/tags/patch-notes/';\n        const response = await got({\n            method: 'get',\n            url,\n        });\n\n        const data = response.data;\n\n        const $ = load(data);\n        const nextData = $('script[id=\"__NEXT_DATA__\"]').text();\n        if (!nextData) {\n            throw new Error('missing next data');\n        }\n        const list: PatchNotesItem[] = JSON.parse(nextData).props.pageProps.page.blades[2].items;\n\n        return {\n            title: 'League of Legends Patch Notes',\n            link: url,\n            item: list.map((item): DataItem => ({\n                title: item.title,\n                description: item.description.body,\n                pubDate: parseDate(item.publishedAt),\n                link: item.action.payload.url,\n                guid: item.analytics.contentId,\n                image: item.media.url,\n                itunes_item_image: item.media.url,\n            })),\n        };\n    },\n};","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/leagueoflegends/patch-notes.ts#L12-L48","documentation":"Thrown by the League of Legends patch-notes handler when the scraped LOL news page contains no <script id=\"__NEXT_DATA__\"> element. The handler relies entirely on that Next.js data island to get the patch list (JSON.parse(nextData).props.pageProps.page.blades[2].items); without it, there is nothing to render.","triggerScenarios":"GET https://www.leagueoflegends.com/en-us/news/tags/patch-notes/ returns HTML but the __NEXT_DATA__ script is absent — because riotgames migrated away from Next.js, changed the script id, rendered client-side only (cheerio/load cannot execute JS), or returned an anti-bot/consent page instead of the real content.","commonSituations":"Site rebuild removing/renaming __NEXT_DATA__; consent/region-redirect page intercepting the request; the data moved to a different blade index or a different data island (e.g. __APP_DATA__); got() received a non-HTML body.","solutions":["Open the URL in an incognito browser, view-source, and confirm whether id=\"__NEXT_DATA__\" still exists","If renamed, update the selector in lib/routes/leagueoflegends/patch-notes.ts:28 (e.g. to __APP_DATA__)","If the page now renders client-side only, switch to Puppeteer/Playwright (requirePuppeteer) so the script is populated","Add a real User-Agent via got headers in case the missing data is from a bot-filtered response"],"exampleFix":"// before\nconst nextData = $('script[id=\"__NEXT_DATA__\"]').text();\nif (!nextData) {\n    throw new Error('missing next data');\n}\n// after — try both Next.js data island shapes\nconst nextData = $('script[id=\"__NEXT_DATA__\"]').text() || $('script[id=\"__APP_DATA__\"]').text();\nif (!nextData) {\n    throw new Error('missing next/app data — LOL site may have migrated; check selectors');\n}","handlingStrategy":"try-catch","validationCode":"async function hasNextData(url: string): Promise<boolean> {\n  const resp = await got({ method: 'get', url });\n  const $ = load(resp.data);\n  return $('script[id=\"__NEXT_DATA__\"]').text().length > 0 || $('script[id=\"__APP_DATA__\"]').text().length > 0;\n}","typeGuard":"interface NextDataEnvelope { props?: { pageProps?: { page?: { blades?: { items?: unknown[] }[] } } } }\nfunction hasNextDataShape(v: unknown): v is NextDataEnvelope {\n  const blades = (v as NextDataEnvelope)?.props?.pageProps?.page?.blades;\n  return Array.isArray(blades) && blades.length > 2 && Array.isArray(blades[2]?.items);\n}","tryCatchPattern":"try { return await handler(); }\ncatch (e) {\n  if (e instanceof Error && e.message === 'missing next data') {\n    // likely SSR migrated or bot-filtered — retry with a real UA, then advise enabling Puppeteer\n    throw new Error('LOL patch notes: __NEXT_DATA__ missing — site migrated or request was bot-filtered');\n  }\n  throw e;\n}","preventionTips":["Send a realistic User-Agent to avoid bot-filtered responses","Try both __NEXT_DATA__ and __APP_DATA__ selectors","Switch to requirePuppeteer if the page renders client-side only","Pin a content-type check to detect HTML-vs-non-HTML responses"],"tags":["scraping","html-parsing","site-restructure","nextjs"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}