DIYgod/RSSHub · error · InvalidParameterError
Invalid channel name
Error message
Invalid channel name
What it means
The 21财经 channel route fetches a remote webMenu.json from static.21jingji.com and verifies the requested channel `name` is a key in that live menu before composing the API URL. InvalidParameterError is thrown if the channel is not present, because the subsequent API call would be meaningless.
Solutions
- Open https://static.21jingji.com/m/webMenu.json and copy an existing key verbatim.
- Fall back to the default by omitting the segment (defaults to '热点').
- If the menu endpoint itself moved, report it to maintainers — the URL may need updating.
Example fix
// before /21caijing/channel/hotnews // not a key in webMenu.json // after /21caijing/channel/热点 // or omit the segment
Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot be fully pre-validated without fetching webMenu.json,
// but you can pre-flight it:
async function channelExists(name) {
const menu = await ofetch('https://static.21jingji.com/m/webMenu.json');
return Object.prototype.hasOwnProperty.call(processMenu(menu), name);
} Type guard
function isInMenu(menu, name): name is string {
return typeof name === 'string' && Object.prototype.hasOwnProperty.call(menu, name);
} Try / catch
try {
return await build21caijingFeed(name);
} catch (e) {
if (e instanceof InvalidParameterError && /Invalid channel name/.test(e.message)) {
// refresh the menu once and retry, else fall back to default '热点'
return await build21caijingFeed('热点');
}
throw e;
} Prevention
- Cache webMenu.json with a short TTL so stale channel names surface quickly.
- Default to '热点' when user input is unverified.
- Watch for InvalidParameterError specifically and degrade rather than fail the whole feed.
When it happens
Trigger: Calling /21caijing/channel/:name with a value that is not a property of the fetched m/webMenu.json — a typo, a renamed channel, or a channel the app retired.
Common situations: The menu changed upstream (channel renamed/removed); copy-pasting a stale name; the default '热点' no longer being present after a redesign.
Related errors
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/dcacfa9990e5838c.
Report an issue: GitHub.
Appendix: source
Thrown at lib/routes/21caijing/channel.ts:57
}
return result;
};
export const handler = async (ctx: Context): Promise<Data> => {
const { name = '热点' } = ctx.req.param();
const limit = Number(ctx.req.query('limit') ?? '30');
const domain = 'm.21jingji.com';
const baseUrl = `https://${domain}`;
const staticBaseUrl = 'https://static.21jingji.com';
const menuUrl: string = new URL('m/webMenu.json', staticBaseUrl).href;
const menuResponse = await ofetch(menuUrl);
const menu = processMenu(menuResponse);
if (!menu.hasOwnProperty(name)) {
throw new InvalidParameterError('Invalid channel name');
}
const currentChannel = menu[name];
const apiUrl: string = new URL(currentChannel.apiUrl, baseUrl).href;
const targetUrl: string = new URL(`#/${currentChannel.url}`, baseUrl).href;
const authUrl: string = new URL('reader/cbhChannelAuth', baseUrl).href;
const targetResponse = await ofetch(targetUrl);
const $: CheerioAPI = load(targetResponse);
const language: string = $('html').attr('lang') ?? 'zh-CN';
const authResponse = await ofetch(authUrl, {
method: 'POST',
responseType: 'json',
});
const response = await ofetch(apiUrl, {View on GitHub (pinned to bed535e087)