DIYgod/RSSHub · error · Error
${tagResponse.msg}
Error message
${tagResponse.msg} What it means
Followin's internal API at /feed/list/tag returns a JSON envelope where success is signaled by code === 2000. Any other code indicates the request was rejected (invalid/expired anti-bot tokens, bad tagId, rate limiting) and the API's msg field carries the human-readable reason, which is re-thrown verbatim. The endpoint is anti-crawler protected and depends on x-bparam and x-gtoken headers derived from the site's build session.
Source
Thrown at lib/routes/followin/tag.ts:56
const { base_info: tagInfo } = queries.find((q) => q.queryKey[0] === '/tag/info/v2').state.data;
return tagInfo;
});
const gToken = await getGToken();
const bParam = getBParam(lang);
const { data: tagResponse } = await got.post(`${apiUrl}/feed/list/tag`, {
headers: {
'x-bparam': JSON.stringify(bParam),
'x-gtoken': gToken,
},
json: {
count: limit,
id: Number.parseInt(tagId),
type: 'tag_discussion_feed',
},
});
if (tagResponse.code !== 2000) {
throw new Error(tagResponse.msg);
}
const list = parseList(tagResponse.data.list.slice(0, limit), lang, buildId);
const items = await Promise.all(list.map((item) => parseItem(item)));
return {
title: `${tagInfo.name} - Followin`,
description: tagInfo.description,
link: `${baseUrl}/${lang}/tag/${tagId}`,
image: tagInfo.logo,
language: lang,
item: items,
};
}
View on GitHub (pinned to bed535e087)
Solutions
- Verify tagId is purely numeric (e.g. 177008) before calling the API, since Number.parseInt(tagId) silently produces NaN for slugs.
- Ensure getBuildId() and getGToken() return fresh values — short-cache or re-fetch them if the feed call rejects with an auth-related msg.
- Inspect the thrown tagResponse.msg: a token/anti-bot message means regenerate bParam/gToken; a 'not found' message means the tagId is wrong.
- Add a retry that re-bootstraps gToken/bParam once before surfacing the error to the user.
Example fix
// before
const gToken = await getGToken();
const bParam = getBParam(lang);
const { data: tagResponse } = await got.post(`${apiUrl}/feed/list/tag`, { ... });
if (tagResponse.code !== 2000) {
throw new Error(tagResponse.msg);
}
// after
if (!/^\d+$/.test(tagId)) {
throw new InvalidParameterError(`tagId must be numeric, got: ${tagId}`);
}
let tagResponse;
for (const attempt of [0, 1]) {
const gToken = await getGToken(attempt === 1);
const bParam = getBParam(lang);
({ data: tagResponse } = await got.post(`${apiUrl}/feed/list/tag`, {
headers: { 'x-bparam': JSON.stringify(bParam), 'x-gtoken': gToken },
json: { count: limit, id: Number.parseInt(tagId), type: 'tag_discussion_feed' },
}));
if (tagResponse.code === 2000) break;
} Defensive patterns
Strategy: validation
Validate before calling
if (!/^\d+$/.test(tagId)) {
throw new InvalidParameterError('tagId must be numeric');
} Type guard
const isNumericId = (v: string): v is string => /^\d+$/.test(v);
Try / catch
try {
const { data: tagResponse } = await got.post(`${apiUrl}/feed/list/tag`, { ... });
} catch (e) {
// tagResponse.code !== 2000 surfaces as a thrown Error with the API msg
if (/token|auth|gtoken|bparam/i.test((e as Error).message)) {
// re-bootstrap tokens once and retry
}
throw e;
} Prevention
- Validate tagId is numeric before Number.parseInt.
- Keep gToken/bParam cache TTL short so they refresh before expiry.
- Log tagResponse.code alongside msg to triage auth vs not-found.
When it happens
Trigger: Posting to apiUrl/feed/list/tag with an expired or stale gToken/bParam, a non-numeric or deleted tagId (Number.parseInt yields NaN), or when Followin's anti-bot layer flags the request. Also triggered if the tag exists but the feed type 'tag_discussion_feed' yields no data and the API signals it with a non-2000 code.
Common situations: Cached buildId/gToken going stale between the getBuildId/getGToken calls and the feed request; deploying without a reachable Followin frontend so token bootstrap fails silently; passing a tagId copied from a URL that is actually a slug rather than a numeric ID.
Related errors
- Failed to retrieve user follows from MangaDex API.
- Failed to retrieve user follows from MangaDex API.
- Failed to retrieve user follows from MangaDex API.
- The database is not exist
- 无法获取用户信息
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/f9fd0c655cf1afae.
Report an issue: GitHub.