DIYgod/RSSHub · error · Error

无法在 HTML 缓存中提取核心数据对象

Error message

无法在 HTML 缓存中提取核心数据对象

What it means

After parsing the __NEXT_DATA__ JSON from comic-walker, the route searches the dehydrated React Query cache for a query whose key references '/api/contents/details/work'. If no matching query is found or it has no state.data, this error is thrown. The query key format is the fragile coupling point — any change in the API path naming breaks the lookup.

Source

Thrown at lib/routes/comic-walker/manga.ts:61

            headers: {
                'Accept-Language': 'ja,en-US;q=0.9,en;q=0.8',
            },
        });

        const $ = load(response);
        const nextDataText = $('#__NEXT_DATA__').text();

        if (!nextDataText) {
            throw new Error('无法解析页面 HTML 数据,可能触发了反爬策略或页面结构巨变');
        }

        const nextData = JSON.parse(nextDataText);
        const queries = nextData.props?.pageProps?.dehydratedState?.queries || [];

        const workQuery = queries.find((q: any) => q.queryKey?.includes('/api/contents/details/work') || (Array.isArray(q.queryKey) && q.queryKey.some((k: any) => typeof k === 'string' && k.includes('work'))));

        if (!workQuery || !workQuery.state?.data) {
            throw new Error('无法在 HTML 缓存中提取核心数据对象');
        }

        const data = workQuery.state.data;
        const work = data.work;

        if (!work) {
            throw new Error('成功获取数据对象,但未找到作品基本信息');
        }

        const mangaTitle = work.title || $('title').text();
        const mangaAuthor = work.authors?.map((author: any) => author.name).join(', ');
        const mangaDescription = work.summary || '';
        const coverImage = work.bookCover || work.thumbnail;

        const firstEpisodes = getEpisodes(data.firstEpisodes);
        const latestEpisodes = getEpisodes(data.latestEpisodes);
        const extraEpisodes = getEpisodes(data.episodes);

View on GitHub (pinned to bed535e087)

Solutions

  1. Log the actual query keys in the dehydratedState to see the new naming pattern.
  2. Broaden the search to match on partial key patterns, or check for alternative query shapes.
  3. Visit the page in a browser, inspect __NEXT_DATA__ in DevTools, and compare the queries array to the expected structure.
  4. Update the queryKey matching logic to use the new pattern once identified.

Example fix

// before
const workQuery = queries.find((q: any) =>
    q.queryKey?.includes('/api/contents/details/work') ||
    (Array.isArray(q.queryKey) && q.queryKey.some((k: any) => typeof k === 'string' && k.includes('work')))
);

// after — log available keys and broaden match
if (!workQuery) {
    const keys = queries.map((q: any) => JSON.stringify(q.queryKey));
    throw new Error(`work query not found in dehydrated cache. Available keys: ${keys.join(' | ')}`);
}
Defensive patterns

Strategy: validation

Validate before calling

const queries = nextData.props?.pageProps?.dehydratedState?.queries || [];
if (queries.length === 0) {
    throw new Error('No React Query entries in dehydrated state');
}
const workQuery = queries.find((q: any) =>
    q.queryKey?.includes('/api/contents/details/work') ||
    (Array.isArray(q.queryKey) && q.queryKey.some((k: any) => typeof k === 'string' && k.includes('work')))
);
if (!workQuery) {
    logger.warn(`Available query keys: ${queries.map(q => JSON.stringify(q.queryKey)).join(', ')}`);
}

Type guard

function hasWorkQuery(queries: any[]): queries is Array<{ queryKey: any[]; state: { data: { work: any } } }> {
    return queries.some(q => q?.state?.data?.work != null);
}

Prevention

When it happens

Trigger: nextData.props.pageProps.dehydratedState.queries is searched with a queryKey containing '/api/contents/details/work' or a key element containing 'work'. The find() returns undefined either because the queries array is empty or the query keys no longer match the expected pattern.

Common situations: Comic Walker renames their internal API endpoint (e.g., from '/api/contents/details/work' to '/api/contents/work/detail'); the dehydratedState structure changes in a Next.js or React Query version upgrade; the manga ID leads to a page where the work query was never fetched (different page type rendered).

Related errors


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