DIYgod/RSSHub · error · Error

Failed to get token

Error message

Failed to get token

What it means

The denonbu (電音部) news route obtains an auth token from the backend API at /auths/token/get using a hardcoded X-API-KEY. If the response payload lacks a token field, the route throws 'Failed to get token'. This token is required for all subsequent API calls to fetch news, events, goods, etc. The token is cached but must be obtained fresh on cache miss.

Source

Thrown at lib/routes/denonbu/news.ts:127

    'X-API-KEY': 'FVpHcMLqyf7v2EubqiLxznC9gVMqBDFFMt4zvkS2',
};
const PRIMARY_CATEGORIES = new Set(['news', 'event', 'goods', 'comic', 'movie', 'music', 'livearchives']);
const CACHE_TOKEN_KEY = 'denonbu-news';

async function getToken(): Promise<string> {
    const cacheToken = await cache.get(CACHE_TOKEN_KEY, false);
    if (cacheToken) {
        return cacheToken;
    }

    const payload = (
        await ofetch(new URL('auths/token/get', BASE_URL).href, {
            headers: COMMON_HEADERS,
        })
    ).payload;
    const { token, expires } = payload;
    if (!token) {
        throw new Error('Failed to get token');
    }
    cache.set(CACHE_TOKEN_KEY, token, expires ? expires - Number(Date.now()) / 1000 - 1 : 3600);
    return token;
}

function buildLink(body: any): string | null {
    switch (body.source_type) {
        case 'main':
        case 'deep-okubo':
        case 'shinsaibashi':
        case 'neotokyo': {
            const { sid, uid } = body;
            if (sid && uid) {
                return `https://denonbu.jp/detail/${sid}/${uid}`;
            }
            return null;
        }
        case 'tw': {

View on GitHub (pinned to bed535e087)

Solutions

  1. Inspect the full response from the auth endpoint — log the payload object to see what was returned.
  2. Check if the X-API-KEY is still valid by testing the endpoint directly (e.g., via curl).
  3. If the key is expired, find the new key by inspecting network requests on denonbu.jp in a browser.
  4. Verify the auths/token/get endpoint path is still correct.
  5. Add error handling for non-200 HTTP responses from ofetch.

Example fix

// before
const payload = (
    await ofetch(new URL('auths/token/get', BASE_URL).href, {
        headers: COMMON_HEADERS,
    })
).payload;
const { token, expires } = payload;
if (!token) {
    throw new Error('Failed to get token');
}

// after — surface the actual response for debugging
const res = await ofetch(new URL('auths/token/get', BASE_URL).href, {
    headers: COMMON_HEADERS,
});
const payload = res.payload;
if (!payload?.token) {
    throw new Error(`Failed to get token. Response: ${JSON.stringify(res).slice(0, 200)}`);
}
Defensive patterns

Strategy: retry

Validate before calling

// Check cache first, then validate API response shape
const cacheToken = await cache.get(CACHE_TOKEN_KEY, false);
if (cacheToken) return cacheToken;

const res = await ofetch(new URL('auths/token/get', BASE_URL).href, { headers: COMMON_HEADERS });
if (!res?.payload) {
    throw new Error(`Denonbu auth endpoint returned unexpected shape: ${JSON.stringify(res).slice(0, 200)}`);
}

Type guard

function hasTokenPayload(res: any): res is { payload: { token: string; expires?: number } } {
    return res?.payload?.token != null && typeof res.payload.token === 'string';
}

Try / catch

try {
    const res = await ofetch(authUrl, { headers: COMMON_HEADERS });
    if (!res.payload?.token) throw new Error('No token in response');
    return res.payload.token;
} catch (e) {
    // Clear potentially stale cache and retry once
    cache.set(CACHE_TOKEN_KEY, null, 0);
    throw new Error(`Failed to obtain denonbu auth token: ${(e as Error).message}`);
}

Prevention

When it happens

Trigger: The ofetch call to BASE_URL/auths/token/get returns a payload object, but payload.token is undefined/null/falsy. This can occur when the hardcoded X-API-KEY is invalid or expired, when the API endpoint changed, or when the server returns an error response that ofetch does not throw on (e.g., 200 with error body).

Common situations: The X-API-KEY 'FVpHcMLqyf7v2EubqiLxznC9gVMqBDFFMt4zvkS2' was rotated or revoked by denonbu.jp; the auth endpoint URL or response format changed; the server is under maintenance and returns a fallback response; rate limiting returns a 429-like body without proper HTTP status.

Related errors


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