{"record":{"id":"7674a2ae20f1f96c","repo":"DIYgod/RSSHub","slug":"failed-to-parse-page-data","errorCode":null,"errorMessage":"Failed to parse page data","messagePattern":"Failed to parse page data","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/xhamster/index.ts","lineNumber":117,"sourceCode":"}\n\nasync function handler(ctx) {\n    const { creators } = ctx.req.param();\n    const pageUrl = `https://xhamster.com/creators/${encodeURIComponent(creators)}/newest`;\n\n    const response = await got(pageUrl);\n\n    const $ = load(response.data);\n    const initialsRaw = $('#initials-script').text();\n    if (!initialsRaw) {\n        throw new Error('Could not locate initials script on page');\n    }\n\n    let initials: Initials;\n    try {\n        initials = extractInitials(initialsRaw);\n    } catch {\n        throw new Error('Failed to parse page data');\n    }\n\n    const creatorName = initials.infoComponent?.pornstarTop?.name ?? creators;\n    const videos = initials.trendingVideoSectionComponent?.videoListProps?.videoThumbProps ?? [];\n\n    const items = videos.map((video) => ({\n        title: `${video.title}${video.isUHD ? ' [4K]' : ''}`,\n        link: video.pageURL,\n        pubDate: video.created ? parseDate(video.created * 1000) : undefined,\n        author: creatorName,\n        description: renderDescription(video),\n        media: {\n            content: {\n                url: video.trailerURL ?? video.pageURL,\n                type: 'video/mp4',\n                ...(video.duration && { duration: video.duration as unknown as string }),\n            },\n            thumbnail: {","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/xhamster/index.ts#L99-L135","documentation":"extractInitials() either failed to match the /window\\.initials\\s*=\\s*(\\S[\\s\\S]*?);?$/ regex (throws 'initials not found') or JSON.parse failed on the captured payload. The handler swallows that detail and re-throws a generic 'Failed to parse page data'.","triggerScenarios":"The #initials-script text exists but its format changed — trailing semicolon handling differs, the assignment was renamed, or the JSON is malformed/truncated — index.ts:114-118.","commonSituations":"xhamster changed how it serializes window.initials (e.g. now uses a JSON <script type=\"application/json\"> instead), or the page injected extra content after the assignment that breaks the greedy regex.","solutions":["Inspect the raw #initials-script text from the RSSHub host to see the new format.","Update the extractInitials regex/parse logic at index.ts:62-68 to match the current serialization.","Report upstream (maintainer eve2ptp) with a sample of the new script payload."],"exampleFix":"// before\nconst match = scriptContent.match(/window\\.initials\\s*=\\s*(\\S[\\s\\S]*?);?$/);\n// after (tolerate trailing content / type-tagged JSON)\nconst match = scriptContent.match(/window\\.initials\\s*=\\s*(\\{[\\s\\S]*?\\})\\s*;?\\s*(?:<\\/script>)?$/);","handlingStrategy":"type-guard","validationCode":"// Validate the script payload shape before parsing\nconst raw = $('#initials-script').text();\nif (!/window\\.initials\\s*=/.test(raw)) {\n    throw new Error('initials assignment missing — page format changed');\n}\nif (!raw.includes('{') || !raw.includes('}')) {\n    throw new Error('initials payload does not look like JSON');\n}","typeGuard":"function isXhamsterParseError(e: unknown): boolean {\n    return e instanceof Error && /Failed to parse page data/i.test(e.message);\n}","tryCatchPattern":"try {\n    initials = extractInitials(initialsRaw);\n} catch (parseErr) {\n    // Preserve the real reason instead of masking it\n    throw new Error(`Failed to parse xhamster initials: ${parseErr}`, { cause: parseErr });\n}","preventionTips":["Don't swallow the inner parse error — chain it so diagnosis is possible.","Make extractInitials tolerant of trailing semicolons/script tags.","Add a snapshot test of the initials regex against a real payload."],"tags":["xhamster","parsing","json","regex","html-structure"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}