DIYgod/RSSHub · error · InvalidParameterError

Invalid UID. UID should start with <b>MS4wLjABAAAA</b>.

Error message

Invalid UID. UID should start with <b>MS4wLjABAAAA</b>.

What it means

Thrown by the Douyin user feed route when the `uid` path parameter does not start with the base64 prefix `MS4wLjABAAAA`. All Douyin `sec_uid` values (the security user ID used in profile URLs) begin with this prefix — it encodes a fixed header in Douyin's protobuf-based ID format. If the uid doesn't match, it's almost certainly the wrong type of identifier (e.g. a short numeric ID, a username, or a malformed value).

Source

Thrown at lib/routes/douyin/user.ts:40

        supportBT: false,
        supportPodcast: false,
        supportScihub: false,
    },
    radar: [
        {
            source: ['douyin.com/user/:uid'],
            target: '/user/:uid',
        },
    ],
    name: '博主',
    maintainers: ['Max-Tortoise', 'Rongronggg9'],
    handler,
};

async function handler(ctx) {
    const uid = ctx.req.param('uid');
    if (!uid.startsWith('MS4wLjABAAAA')) {
        throw new InvalidParameterError('Invalid UID. UID should start with <b>MS4wLjABAAAA</b>.');
    }
    const routeParams = Object.fromEntries(new URLSearchParams(ctx.req.param('routeParams')));
    const embed = fallback(undefined, queryToBoolean(routeParams.embed), false); // embed video
    const iframe = fallback(undefined, queryToBoolean(routeParams.iframe), false); // embed video in iframe
    const relay = resolveUrl(routeParams.relay, true, true); // embed video behind a reverse proxy

    const pageUrl = `https://www.douyin.com/user/${uid}`;

    const pageData = (await cache.tryGet(
        `douyin:user:${uid}`,
        async () => {
            let postData;
            const context = await playwright();
            const page = await context.newPage();
            await page.route('**/*', (route) => {
                const request = route.request();
                request.resourceType() === 'document' || request.resourceType() === 'script' || request.resourceType() === 'xhr' ? route.continue() : route.abort();
            });

View on GitHub (pinned to bed535e087)

Solutions

  1. Find the correct sec_uid from the user's profile URL: https://www.douyin.com/user/MS4wLjABAAAA... — copy everything after /user/.
  2. Ensure the full sec_uid is included — it is typically 70+ characters long.
  3. Do not use the numeric user ID or the @username — only the sec_uid works.
Defensive patterns

Strategy: validation

Validate before calling

function isValidDouyinUid(uid: string): boolean {
    return uid.startsWith('MS4wLjABAAAA');
}

const uid = userInput;
if (!isValidDouyinUid(uid)) {
    throw new Error(`Invalid UID. Must start with 'MS4wLjABAAAA'. Got: ${uid.substring(0, 20)}...`);
}

Type guard

function isDouyinSecUid(value: string): boolean {
    return value.startsWith('MS4wLjABAAAA');
}

Try / catch

try {
    const feed = await fetch(`${rsshubUrl}/douyin/user/${uid}`);
} catch (e) {
    if (e.message.includes('Invalid UID')) {
        console.error('Use the sec_uid from the profile URL, not the numeric ID or username.');
    }
    throw e;
}

Prevention

When it happens

Trigger: User supplies a short numeric user ID instead of the sec_uid; user supplies a Douyin username instead of sec_uid; the uid was truncated or URL-decoded incorrectly (the sec_uid contains characters that may need encoding).

Common situations: Developer confuses Douyin's numeric user ID with the sec_uid; the URL was copy-pasted partially; URL encoding of special characters in the sec_uid (it contains hyphens and underscores which are URL-safe, but if %-encoded may not match).

Related errors


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