DIYgod/RSSHub · error · Error

成功获取数据对象,但未找到作品基本信息

Error message

成功获取数据对象,但未找到作品基本信息

What it means

The dehydrated React Query was found and its state.data was non-null, but state.data.work is missing. This is a shape-level mismatch: the API response object exists but does not contain the expected 'work' property that holds manga metadata (title, authors, summary, cover, episodes).

Solutions

  1. Log the full data object to see its actual top-level keys.
  2. Tighten the queryKey matching to avoid accidentally matching a non-work query.
  3. Check if the API now nests work data under a different key (e.g., data.result.work or data.data.work).
  4. Verify the manga ID is valid by checking the API response status.

Example fix

// before
const data = workQuery.state.data;
const work = data.work;
if (!work) {
    throw new Error('成功获取数据对象,但未找到作品基本信息');
}

// after — expose available keys
const data = workQuery.state.data;
const work = data.work;
if (!work) {
    throw new Error(`Data object missing 'work' key. Available keys: ${Object.keys(data).join(', ')}`);
}
Defensive patterns

Strategy: type-guard

Type guard

function hasWorkData(data: any): data is { work: { title: string; authors: any[]; summary: string } } {
    return data != null && typeof data === 'object' && typeof data.work === 'object' && data.work != null;
}

Prevention

When it happens

Trigger: workQuery.state.data is truthy but data.work is undefined or null. This can happen when the API response embeds work data under a different key, when the response represents an error state (e.g., { error: '...' }), or when the query resolved with partial data.

Common situations: The API response schema changed — 'work' was renamed or nested one level deeper; the manga was deleted and the API returns a soft-error object with status but no work field; a different query (e.g., a related-works query) was matched by the loose 'work' substring check and contains unrelated data.

Related errors


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

Appendix: source

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

        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);

        const seenCodes = new Set<string>();
        const allChapters = [...firstEpisodes, ...latestEpisodes, ...extraEpisodes]
            .filter((ep) => {
                if (ep?.code && !seenCodes.has(ep.code)) {
                    seenCodes.add(ep.code);
                    return true;
                }

View on GitHub (pinned to bed535e087)