{"record":{"id":"bc7ee93fd25ef6f9","repo":"DIYgod/RSSHub","slug":"invalid-data-received-from-api","errorCode":null,"errorMessage":"Invalid data received from API","messagePattern":"Invalid data received from API","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/skeb/index.ts","lineNumber":116,"sourceCode":"\n    if (!Object.hasOwn(categoryMap, category)) {\n        throw new Error('Invalid category');\n    }\n\n    const url = `${baseUrl}/api`;\n\n    const apiData = await cache.tryGet(\n        url,\n        async () => {\n            const data = await ofetch(url);\n            return data;\n        },\n        config.cache.routeExpire,\n        false\n    );\n\n    if (!apiData || typeof apiData !== 'object') {\n        throw new Error('Invalid data received from API');\n    }\n\n    const items = await cache.tryGet(category, async () => {\n        if (!Object.hasOwn(apiData, category) || !Array.isArray(apiData[category])) {\n            return [];\n        }\n\n        const processItem = workCategories.has(category) ? processWork : processCreator;\n        return (await Promise.all(apiData[category].map(async (item) => await processItem(item)).filter(Boolean))) as DataItem[];\n    });\n\n    return {\n        title: `Skeb - ${categoryMap[category]}`,\n        link: `${baseUrl}/#${category}`,\n        item: items as DataItem[],\n    };\n}\n","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/skeb/index.ts#L98-L134","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check if the Skeb API is reachable directly: curl https://skeb.jp/api and inspect the response content-type and body.","If Cloudflare is blocking the instance, set a realistic browser User-Agent via config.trueUA or deploy behind a residential IP / proxy.","Clear the cached bad value if cache.tryGet stored a null: restart the instance or flush the Redis key for the API URL.","If the API endpoint has moved, update the `url` constant in the handler to the new path."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"const apiData = await cache.tryGet(url, async () => await ofetch(url), config.cache.routeExpire, false);\nif (!apiData || typeof apiData !== 'object' || Array.isArray(apiData)) {\n    throw new Error('Invalid data received from API');\n}","typeGuard":"function isApiDataObject(data: unknown): data is Record<string, unknown> {\n    return data !== null && typeof data === 'object' && !Array.isArray(data);\n}","tryCatchPattern":"try {\n    const apiData = await cache.tryGet(url, /* ... */);\n    if (!isApiDataObject(apiData)) throw new Error('Invalid data received from API');\n} catch (e) {\n    logger.error('Skeb API fetch failed', e);\n    throw e;\n}","preventionTips":["Monitor the Skeb API for format changes by logging the content-type of responses.","Use a typed interface for the API response so TypeScript can catch shape mismatches at compile time.","Set up alerting when this error spikes, as it usually indicates Cloudflare blocking or upstream changes."],"tags":["api","upstream","anti-crawler","data-integrity","skeb"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}