DIYgod/RSSHub · error · Error

Failed to extract required data from JSON

Error message

Failed to extract required data from JSON

What it means

Thrown after the SSR_HYDRATED_DATA script content is parsed into JSON but the expected AuthorVideoList.videoList or AuthorDetailInfo fields are absent. The route destructures these two paths from the parsed object; if either is falsy the feed cannot be built. This indicates the JSON shape changed or the regex captured an incomplete/truncated object.

Source

Thrown at lib/routes/ixigua/user-video.tsx:55

    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) => ({
            title: i.title,
            description: renderToString(<IxiguaVideoDescription i={i} disableEmbed={disableEmbed} />),
            link: `${host}/${i.groupId}`,
            pubDate: parseDate(i.publishTime * 1000),
            author: userInfo.name,
        })),
    };
}

const IxiguaVideoDescription = ({ i, disableEmbed }: { i: any; disableEmbed?: string }) => (
    <>

View on GitHub (pinned to bed535e087)

Solutions

  1. Inspect the full jsData string to confirm whether AuthorVideoList and AuthorDetailInfo keys exist — if present but missed, the regex is truncating; switch to a balanced-brace extraction or parse the whole script body.
  2. If the keys were renamed, update the destructuring to match the new field names.
  3. Differentiate between 'no videos' and 'missing data' — return an empty feed (allowEmpty) for users with no videos instead of throwing.
  4. Log the top-level keys of jsonData when the guard fires to accelerate diagnosis.

Example fix

// before
const jsonData = JSON.parse(jsData.match(/var\s+data\s*=\s*(\{.*?\});/s)?.[1].replaceAll('undefined', 'null') || '{}');

// after — extract the full balanced object instead of a non-greedy truncation
const start = jsData.indexOf('{');
let depth = 0, end = -1;
for (let i = start; i < jsData.length; i++) {
    if (jsData[i] === '{') depth++;
    else if (jsData[i] === '}') { depth--; if (depth === 0) { end = i; break; } }
}
const jsonData = JSON.parse(jsData.slice(start, end + 1).replaceAll('undefined', 'null'));
Defensive patterns

Strategy: type-guard

Validate before calling

// After parsing, verify the expected keys exist before destructuring
const jsonData = JSON.parse(rawJson);
if (!('AuthorVideoList' in jsonData) || !('AuthorDetailInfo' in jsonData)) {
    throw new Error(`Unexpected ixigua JSON shape. Top-level keys: ${Object.keys(jsonData).join(', ')}`);
}

Type guard

interface IxiguaData {
    AuthorVideoList: { videoList: unknown[] };
    AuthorDetailInfo: { name: string; introduce?: string };
}
function isIxiguaData(d: unknown): d is IxiguaData {
    return typeof d === 'object' && d !== null &&
        'AuthorVideoList' in d && 'AuthorDetailInfo' in d &&
        Array.isArray((d as any).AuthorVideoList?.videoList);
}

Try / catch

try {
    const jsonData = JSON.parse(jsData);
    if (!isIxiguaData(jsonData)) {
        throw new Error('Failed to extract required data from JSON');
    }
    // ...use jsonData with full type safety
} catch (e) {
    throw new Error(`ixigua JSON parse failed: ${(e as Error).message}`, { cause: e });
}

Prevention

When it happens

Trigger: The regex /var\s+data\s*=\s*(\{.*?\});/s uses a non-greedy match that stops at the first '} ;' sequence, which can truncate a deeply nested object and yield partial JSON missing the AuthorVideoList/AuthorDetailInfo keys. Also fires when the user genuinely has no videos (videoList is empty/undefined in the SSR payload) or when ixigua renames these keys in a frontend version bump.

Common situations: ixigua restructures its SSR data and renames AuthorVideoList to a different key. A user with a brand-new or deactivated account has an empty video list. The regex's non-greedy quantifier captures only the first nested object, losing the rest of the payload.

Related errors


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