DIYgod/RSSHub · warning · InvalidParameterError

Provide a valid Misskey username

Error message

Provide a valid Misskey username

What it means

Thrown as InvalidParameterError by the Misskey user-timeline route when the :username parameter does not match the regex /@?(\w+)@(\w+\.\w+)/ — i.e. it is not a WebFinger 'acct' style identifier (user@host.tld, with optional leading @). The regex captures both the pure username and the host; failure to capture either is a client error.

Source

Thrown at lib/routes/misskey/user-timeline.ts:49

    },
    features: {
        requireConfig: false,
        requirePuppeteer: false,
        antiCrawler: false,
        supportBT: false,
        supportPodcast: false,
        supportScihub: false,
    },
    name: 'User timeline',
    maintainers: ['siygle', 'SnowAgar25', 'HanaokaYuzu'],
    handler,
};

async function handler(ctx): Promise<Data> {
    const username = ctx.req.param('username');
    const [, pureUsername, site] = username.match(/@?(\w+)@(\w+\.\w+)/) || [];
    if (!pureUsername || !site) {
        throw new InvalidParameterError('Provide a valid Misskey username');
    }
    if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
        throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
    }

    const routeParams = querystring.parse(ctx.req.param('routeParams'));
    const withRenotes = fallback(undefined, queryToBoolean(routeParams.withRenotes), false);
    const mediaOnly = fallback(undefined, queryToBoolean(routeParams.mediaOnly), false);
    const simplifyAuthor = fallback(undefined, queryToBoolean(routeParams.simplifyAuthor), false);

    // Check for conflicting parameters
    if (withRenotes && mediaOnly) {
        throw new InvalidParameterError('withRenotes and mediaOnly cannot both be true.');
    }

    const { accountData, avatarUrl } = await utils.getUserTimelineByUsername(pureUsername, site, {
        withRenotes,
        mediaOnly,

View on GitHub (pinned to bed535e087)

Solutions

  1. Format the username as an acct: '@user@instance.tld' or 'user@instance.tld' (the leading @ is optional), e.g. /misskey/user/@alice@misskey.io.
  2. Ensure the host part has at least one dot (a real domain).
  3. Strip any surrounding URL scheme or path before passing the value.
Defensive patterns

Strategy: validation

Validate before calling

const username = ctx.req.param('username');
const m = username.match(/^@?(\w+)@(\w+\.\w+)$/);
if (!m) {
    throw new InvalidParameterError(`Provide a username in acct form user@host.tld (leading @ optional); got: ${username}`);
}
const [, pureUsername, site] = m;

Type guard

function isAcct(username: string): boolean {
    return typeof username === 'string' && /^@?\w+@\w+\.\w+$/.test(username);
}

Prevention

When it happens

Trigger: Caller requests /misskey/user-timeline/:username with a value like 'alice' (no host), 'alice@' (no domain), '@alice@host' where host has no dot, or a value containing characters outside \w. pureUsername or site is undefined, so it throws.

Common situations: User supplies just the handle without the instance domain; user supplies a URL instead of an acct; the instance host is a single-label name without a TLD (rare).

Related errors


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