DIYgod/RSSHub · error · Error

${data.errors[0].detail}

Error message

${data.errors[0].detail}

What it means

Re-throws the MangaDex API's own error detail when fetching a single manga's metadata (GET /manga/:id). The handler checks data.result === 'error' and surfaces data.errors[0].detail verbatim, so the actual message is whatever MangaDex returned (e.g. 'Manga not found', rate-limit detail). It is cached under mangadex:manga-meta:<id>.

Source

Thrown at lib/routes/mangadex/_feed.ts:30

 *
 * @author chrisis58, vzz64
 * @param id manga id
 * @param lang language(s), absent for default
 * @param needCover whether to fetch cover
 * @returns title, description, and cover of the manga
 */
const getMangaMeta = async (id: string, needCover: boolean = true, lang?: string | string[]) => {
    const includes = needCover ? ['cover_art'] : [];

    const rawMangaMeta = (await cache.tryGet(`mangadex:manga-meta:${id}`, async () => {
        const { data } = await got.get(
            `${constants.API.MANGA_META}${id}${toQueryString({
                includes,
            })}`
        );

        if (data.result === 'error') {
            throw new Error(data.errors[0].detail);
        }
        return data.data;
    })) as any;

    const relationships = (rawMangaMeta.relationships || []) as Array<{ type: string; id: string; attributes: any }>;

    const languages = [
        ...(typeof lang === 'string' ? [lang] : lang || []),
        ...(await getFilteredLanguages()),
        rawMangaMeta.attributes.originalLanguage, // fallback to original language
    ].filter(Boolean);

    // combine title and altTitles
    const titles = {
        ...rawMangaMeta.attributes.title,
        ...Object.fromEntries(rawMangaMeta.attributes.altTitles.flatMap((element) => Object.entries(element))),
    };

View on GitHub (pinned to bed535e087)

Solutions

  1. Validate the manga id is a UUID and exists by opening https://api.mangadex.org/manga/<id> in a browser.
  2. If rate-limited, wait and let the cache entry (mangadex:manga-meta:<id>) expire before retrying.
  3. Surface a clearer error by wrapping: catch and re-throw with the requested id included.
  4. If the manga was deleted, remove the subscription feeding this id.
Defensive patterns

Strategy: validation

Validate before calling

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
function validateMangaId(id: string) {
    if (!UUID_RE.test(id)) {
        throw new Error(`Invalid MangaDex manga id: ${id}`);
    }
}

Type guard

interface MangadexErrorResponse {
    result: 'ok' | 'error';
    errors?: Array<{ detail: string }>;
}
const isMangadexErrorBody = (v: unknown): v is MangadexErrorResponse =>
    typeof v === 'object' && v !== null && (v as { result?: string }).result === 'error';

Try / catch

try {
    meta = await getMangaMeta(id);
} catch (e) {
    if (/not found/i.test((e as Error).message)) {
        // drop the bad id from the source list rather than failing the whole feed
        continue;
    }
    throw e;
}

Prevention

When it happens

Trigger: GET https://api.mangadex.org/manga/<id>?includes[]=cover_art where <id> is not a valid manga UUID, refers to a deleted/restricted manga, or the request was rate-limited (429 returned in-body).

Common situations: User passed a malformed or non-UUID manga id in the route; manga was deleted/taken down; RSSHub IP temporarily rate-limited by MangaDex; downstream route handed a chapter/group id where a manga id was expected.

Related errors


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