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
- Inspect the full response from the auth endpoint — log the payload object to see what was returned.
- Check if the X-API-KEY is still valid by testing the endpoint directly (e.g., via curl).
- If the key is expired, find the new key by inspecting network requests on denonbu.jp in a browser.
- Verify the auths/token/get endpoint path is still correct.
- 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
- Monitor the hardcoded X-API-KEY for expiration — extract it dynamically if possible.
- Log the full auth response when token is missing to detect API changes.
- Ensure cache TTL for the token is shorter than the actual expiry to avoid stale tokens.
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.