DIYgod/RSSHub · error · Error

Invalid data received from API

Error message

Invalid data received from API

What it means

Thrown as a plain Error after fetching the Skeb homepage JSON API (https://skeb.jp/api) via cache.tryGet when the returned value is falsy (null, undefined, empty string) or not an object. This is a runtime data-integrity guard: it detects when the upstream API is down, returns an error page, or is blocked by anti-crawler measures. The check `!apiData || typeof apiData !== 'object'` ensures the subsequent property access on apiData[category] is safe.

Source

Thrown at lib/routes/skeb/index.ts:116

    if (!Object.hasOwn(categoryMap, category)) {
        throw new Error('Invalid category');
    }

    const url = `${baseUrl}/api`;

    const apiData = await cache.tryGet(
        url,
        async () => {
            const data = await ofetch(url);
            return data;
        },
        config.cache.routeExpire,
        false
    );

    if (!apiData || typeof apiData !== 'object') {
        throw new Error('Invalid data received from API');
    }

    const items = await cache.tryGet(category, async () => {
        if (!Object.hasOwn(apiData, category) || !Array.isArray(apiData[category])) {
            return [];
        }

        const processItem = workCategories.has(category) ? processWork : processCreator;
        return (await Promise.all(apiData[category].map(async (item) => await processItem(item)).filter(Boolean))) as DataItem[];
    });

    return {
        title: `Skeb - ${categoryMap[category]}`,
        link: `${baseUrl}/#${category}`,
        item: items as DataItem[],
    };
}

View on GitHub (pinned to bed535e087)

Solutions

  1. Check if the Skeb API is reachable directly: curl https://skeb.jp/api and inspect the response content-type and body.
  2. If Cloudflare is blocking the instance, set a realistic browser User-Agent via config.trueUA or deploy behind a residential IP / proxy.
  3. Clear the cached bad value if cache.tryGet stored a null: restart the instance or flush the Redis key for the API URL.
  4. If the API endpoint has moved, update the `url` constant in the handler to the new path.
Defensive patterns

Strategy: type-guard

Validate before calling

const apiData = await cache.tryGet(url, async () => await ofetch(url), config.cache.routeExpire, false);
if (!apiData || typeof apiData !== 'object' || Array.isArray(apiData)) {
    throw new Error('Invalid data received from API');
}

Type guard

function isApiDataObject(data: unknown): data is Record<string, unknown> {
    return data !== null && typeof data === 'object' && !Array.isArray(data);
}

Try / catch

try {
    const apiData = await cache.tryGet(url, /* ... */);
    if (!isApiDataObject(apiData)) throw new Error('Invalid data received from API');
} catch (e) {
    logger.error('Skeb API fetch failed', e);
    throw e;
}

Prevention

When it happens

Trigger: The Skeb /api endpoint returns a non-JSON response (e.g. an HTML Cloudflare challenge page, a 502 gateway error body, or an empty string). This can also happen if the ofetch call silently resolves to null in an edge case, or if a cached null/undefined value is served by cache.tryGet with the `false` (no-revalidate) flag.

Common situations: Skeb is behind Cloudflare and returns a challenge page instead of JSON; the instance's IP is rate-limited or geo-blocked; the API URL structure changed after a Skeb site update; or a previous failed fetch cached a null result.

Related errors


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