DIYgod/RSSHub · error · Error
Failed to find SSR_HYDRATED_DATA
Error message
Failed to find SSR_HYDRATED_DATA
What it means
Thrown by the ixigua user-video route when the fetched user homepage HTML does not contain a <script id="SSR_HYDRATED_DATA"> element. The route scrapes server-side-rendered JSON embedded in that tag to obtain the video list and user info. When ixigua serves a different page (anti-bot wall, login redirect, redesigned DOM, or an invalid/expired UID), the selector returns undefined and this guard fires.
Source
Thrown at lib/routes/ixigua/user-video.tsx:44
target: '/user/video/:uid',
},
],
name: '用户视频投稿',
maintainers: ['FlashWingShadow', 'Fatpandac', 'pseudoyu'],
handler,
};
async function handler(ctx) {
const uid = ctx.req.param('uid');
const disableEmbed = ctx.req.param('disableEmbed');
const url = `${host}/home/${uid}/?wid_try=1`;
const { data } = await got(url);
const $ = load(data);
const jsData = $('#SSR_HYDRATED_DATA').html();
if (!jsData) {
throw new Error('Failed to find SSR_HYDRATED_DATA');
}
const jsonData = JSON.parse(jsData.match(/var\s+data\s*=\s*(\{.*?\});/s)?.[1].replaceAll('undefined', 'null') || '{}');
const {
AuthorVideoList: { videoList: videoInfos },
AuthorDetailInfo: userInfo,
} = jsonData;
if (!videoInfos || !userInfo) {
throw new Error('Failed to extract required data from JSON');
}
return {
title: `${userInfo.name} 的西瓜视频`,
link: url,
description: userInfo.introduce,
item: videoInfos.map((i) => ({View on GitHub (pinned to bed535e087)
Solutions
- Verify the UID is correct by opening https://www.ixigua.com/home/{uid}/ in a browser and confirming the profile loads with videos.
- Check whether ixigua is returning an anti-bot/verification page — inspect the raw response body; if so the route needs updated headers, cookies, or Puppeteer handling.
- If the DOM changed, update the selector $('#SSR_HYDRATED_DATA') and the regex /var\s+data\s*=\s*(\{.*?\});/s to match the new embedding format.
- Add a more descriptive error that includes the response URL and a snippet of the body to aid future debugging.
Example fix
// before
const jsData = $('#SSR_HYDRATED_DATA').html();
if (!jsData) {
throw new Error('Failed to find SSR_HYDRATED_DATA');
}
// after — surface what was actually returned so the failure is diagnosable
const jsData = $('#SSR_HYDRATED_DATA').html();
if (!jsData) {
const snippet = $.html().slice(0, 200);
throw new Error(`Failed to find SSR_HYDRATED_DATA for uid ${uid}. Response started with: ${snippet}`);
} Defensive patterns
Strategy: validation
Validate before calling
// Before fetching, sanity-check the uid is a non-empty numeric string
const uid = ctx.req.param('uid');
if (!/^\d+$/.test(uid)) {
throw new InvalidParameterError(`uid must be numeric, got '${uid}'`);
}
// Then fetch and verify the response looks like a profile page before selecting
const { data } = await got(url);
if (!data.includes('SSR_HYDRATED_DATA')) {
// likely an anti-bot page; surface a diagnostic instead of the generic error
throw new Error(`ixigua did not return SSR data for uid ${uid}; possible anti-bot block`);
} Type guard
function hasSsrHydratedData($: cheerio.CheerioAPI): $ is cheerio.CheerioAPI & { __ssr: true } {
return $('#SSR_HYDRATED_DATA').html() != null;
} Try / catch
try {
const jsData = $('#SSR_HYDRATED_DATA').html();
if (!jsData) throw new Error('Failed to find SSR_HYDRATED_DATA');
// ...process
} catch (e) {
// Log the response URL + body length, then rethrow with context
throw new Error(`${(e as Error).message} (uid=${uid}, bodyLen=${data.length})`, { cause: e });
} Prevention
- Validate the uid format before the network call.
- Cache the SSR data extraction with cache.tryGet keyed on uid to reduce repeated anti-bot exposure.
- Monitor for a spike in this error — it signals an upstream site change or block.
- If ixigua blocks RSSHub's IP, consider Puppeteer-based fetching with the requirePuppeteer feature flag.
When it happens
Trigger: Calling /ixigua/user/video/:uid where the UID is invalid, deleted, or the user has no public videos. Also triggered when ixigua returns an anti-crawler interstitial, a Cookie/verification page, or when the site redesigns and renames the SSR_HYDRATED_DATA script tag. A got() response that is HTML but not the expected profile page (e.g. a 200-status error page) also triggers it.
Common situations: ixigua tightens anti-crawler measures and starts returning a verification challenge instead of the profile HTML. The user copies the wrong UID (e.g. a short numeric id instead of the long internal one). The site ships a frontend rewrite and the embedded data script id changes. RSSHub's got() request is rate-limited and gets a throttle page.
Related errors
- Cannot find n-token
- WapHomeRenderData 数据未找到
- Failed to fetch thread data
- LSD token not found
- this route is empty, please check the original site or <a hr
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/95c85ab5d5b5c767.
Report an issue: GitHub.