DIYgod/RSSHub · error · Error

Failed to retrieve user settings from MangaDex API.

Error message

Failed to retrieve user settings from MangaDex API.

What it means

Thrown when GET /settings (requires Bearer access token) returns a body without a settings field. Used to derive the user's filtered/excluded languages, so a failure here breaks every MangaDex route that depends on reading-status or language filtering.

Source

Thrown at lib/routes/mangadex/_profile.ts:24

import getToken from './_access';
import constants from './_constants';

const getSetting = async () => {
    const accessToken = await getToken();

    return cache.tryGet(
        'mangadex:settings',
        async () => {
            const response = await got.get(constants.API.SETTING, {
                headers: {
                    Authorization: `Bearer ${accessToken}`,
                    'User-Agent': config.trueUA,
                },
            });

            const setting = response?.data?.settings;
            if (!setting) {
                throw new Error('Failed to retrieve user settings from MangaDex API.');
            }

            return setting;
        },
        config.cache.contentExpire,
        false
    );
};

const getFilteredLanguages = async (ingoreConfigNotFountError: boolean = true) => {
    try {
        const settings = (await getSetting()) as any;
        return settings.userPreferences.filteredLanguages as string[];
    } catch (error) {
        if (ingoreConfigNotFountError && error instanceof ConfigNotFoundError) {
            return [];
        }
        throw error;

View on GitHub (pinned to bed535e087)

Solutions

  1. Ensure MANGADEX_CLIENT_ID/SECRET plus username/password (or refresh token) are set so getToken can mint an access token.
  2. Flush the cache key mangadex:access-token to force a fresh token on next request.
  3. Confirm https://api.mangadex.org/settings works with the same token via curl.
  4. If getFilteredLanguages is optional for your route, call it with ignoreConfigNotFoundError=false and degrade gracefully.
Defensive patterns

Strategy: try-catch

Validate before calling

if (!config.mangadex.clientId || !config.mangadex.clientSecret) {
    // settings endpoint requires auth; skip language filtering instead of crashing
    return [];
}

Type guard

interface SettingsResponse { settings?: Record<string, unknown>; }
const hasSettings = (v: unknown): v is SettingsResponse =>
    typeof v === 'object' && v !== null && typeof (v as SettingsResponse).settings === 'object';

Try / catch

try {
    settings = await getSetting();
} catch (e) {
    // getFilteredLanguages already supports ignoreConfigNotFoundError; degrade to defaults
    settings = {};
}

Prevention

When it happens

Trigger: GET https://api.mangadex.org/settings with Authorization: Bearer <accessToken> where response.data.settings is undefined. Caused by a missing/invalid/expired access token (401 returned in body), the settings endpoint being down, or an account with no settings object yet.

Common situations: MANGADEX_* auth env unset so accessToken is empty; access token cache (mangadex:access-token) holds a stale token past the 15-min TTL; MangaDex settings API temporarily unavailable; user account in a state that returns no settings.

Related errors


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