DIYgod/RSSHub · error · InvalidParameterError
Invalid user
Error message
Invalid user
What it means
Thrown by substack/subscribe.ts:32 as an InvalidParameterError when isValidHost(user) returns false. isValidHost (lib/utils/valid-host.ts) only checks the subdomain SHAPE via /^\dA-Z(?:[\dA-Z-]{0,61}[\dA-Z])?$/i — it does NOT verify the Substack exists. It rejects empty values, values starting/ending with '-', values over 63 chars, and any value containing '.', '_', or other non-hostname characters. Existence of the publication is checked separately by the later ofetch to https://<user>.substack.com/feed.
Source
Thrown at lib/routes/substack/subscribe.ts:32
parameters: { user: 'Username of the Substack' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
name: 'Substack Subscription',
maintainers: ['pseudoyu'],
handler,
};
async function handler(ctx) {
const user = ctx.req.param('user');
if (!isValidHost(user)) {
throw new InvalidParameterError('Invalid user');
}
const response = await ofetch(`https://${user}.substack.com/feed`);
const feed = await parser.parseString(response);
return {
title: feed.title ?? 'Substack',
description: feed.description ?? `${user}'s Substack`,
link: feed.link ?? `https://${user}.substack.com`,
image: feed.image?.url ?? '',
item: feed.items.map((item) => ({
title: item.title ?? 'Untitled',
description: item['content:encoded'] ?? item.content ?? '',
link: item.link ?? '',
pubDate: item.pubDate ? parseDate(item.pubDate) : undefined,
guid: item.guid ?? '',
author: item.creator ?? user,
})),View on GitHub (pinned to bed535e087)
Solutions
- Pass only the bare substack subdomain — the part before '.substack.com' (e.g. 'mangoread', not 'https://mangoread.substack.com').
- Strip leading/trailing hyphens and whitespace; ensure length is <= 63 and contains only letters, digits, and internal hyphens.
- For custom-domain Substackes this route cannot be used — subscribe via the publication's own RSS feed URL directly.
Example fix
// before GET /substack/subscribe/mangoread.substack.com // after GET /substack/subscribe/mangoread
Defensive patterns
Strategy: validation
Validate before calling
import { isValidHost } from '@/utils/valid-host';
// Run the same check the route runs, before constructing the URL.
function isValidSubstackUser(user: string): boolean {
return isValidHost(user);
} Type guard
import { isValidHost } from '@/utils/valid-host';
function isSubstackSubdomain(user: string): user is string {
return typeof user === 'string'
&& user.length > 0
&& user.length <= 63
&& !user.startsWith('-')
&& !user.endsWith('-')
&& /^[\da-z-]+$/i.test(user)
&& isValidHost(user);
} Prevention
- Pass only the subdomain part before '.substack.com' — no protocol, no dots, no path.
- This route cannot serve custom-domain Substackes; use the publication's own RSS URL for those.
- Trim leading/trailing whitespace and hyphens before submitting.
When it happens
Trigger: /substack/subscribe/<user> where user has a dot (custom-domain Substackes), underscore, leading/trailing hyphen, is empty, or exceeds 63 chars. Also fires when the user passes a full URL, an email, or includes a trailing slash/space.
Common situations: Substack publication on a custom domain (e.g. newsletter.example.com) which does not fit the <user>.substack.com model; user pastes the full Substack URL or an email address as the param; trailing whitespace or slash from a copy-paste.
Related errors
- Invalid column
- Invalid column
- User Not Found
- Unsupported game: ${game}. Supported games: ${Object.keys(GA
- Invalid keyword
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/52401633691648eb.
Report an issue: GitHub.