DIYgod/RSSHub · warning · InvalidParameterError

User not found

Error message

User not found

What it means

InvalidParameterError from the Twitter developer-API cacheTryGet helper: getUserData returned no `id_str`, so the requested user/username does not resolve on Twitter. The helper also poisons the cache with an empty entry to avoid repeated lookups, then throws.

Solutions

  1. Verify the handle exists on x.com.
  2. Flush the cache key `twitter-userdata-{id}` to force a fresh lookup if the user was recently restored/renamed.
  3. Confirm the app has `tweet.read` and `users.read` scopes.
Defensive patterns

Strategy: try-catch

Validate before calling

const userData = await getUserData(_id);
if (userData?.id_str === undefined) throw new InvalidParameterError(`Twitter user not found: ${_id}`);

Type guard

const isUserData = (u: unknown): u is { id_str: string } => typeof u === 'object' && u !== null && typeof (u as any).id_str === 'string';

Try / catch

try { return await cacheTryGet(_id, params, operationName, func); }
catch (e) { if (e instanceof InvalidParameterError && /User not found/.test(e.message)) { await cache.set(`twitter-userdata-${_id}`, undefined); /* allow retry after rename */ } throw e; }

Prevention

When it happens

Trigger: Calling a developer-API function for an id/username that Twitter returns no data for — `userData.id_str` is undefined on line 224, so line 225 caches `''` and line 226 throws 'User not found'.

Common situations: Username typo, suspended/deleted account, handle renamed, or the developer API lacks the lookup scope; the cached empty entry will keep masking it until contentExpire lapses.

Related errors


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

Appendix: source

Thrown at lib/routes/twitter/api/developer-api/api.ts:227

    return (response?.data ?? []).map((tweet) => mapTweetToLegacy(tweet, response.includes, cacheMap));
};

const getUserData = (id: string) =>
    cache.tryGet(`twitter-userdata-${id}`, async () => {
        const client = await getAppClient();
        const params = {
            'user.fields': 'profile_image_url,description,verified,url',
        };
        const response = id.startsWith('+') ? await client.v2.user(id.slice(1), params) : await client.v2.userByUsername(id, params);
        return mapUserToLegacy(response?.data) ?? '';
    });

const cacheTryGet = async (_id: string, params: Record<string, any> | undefined, operationName: string, func: (id: string, params?: Record<string, any>) => Promise<any>) => {
    const userData: any = await getUserData(_id);
    const id = userData?.id_str;
    if (id === undefined) {
        cache.set(`twitter-userdata-${_id}`, '', config.cache.contentExpire);
        throw new InvalidParameterError('User not found');
    }
    return cache.tryGet(getTwitterUserCacheKey(id, operationName, params), () => func(id, params), config.cache.routeExpire, false);
};

const getUserTimeline = async (id: string, params?: Record<string, any>, options: Record<string, any> = {}) => {
    const client = await getAppClient();
    const response = await client.v2.get(`users/${id}/tweets`, {
        max_results: params?.count ?? 20,
        expansions: 'author_id,attachments.media_keys,referenced_tweets.id,referenced_tweets.id.author_id',
        'tweet.fields': 'created_at,entities,conversation_id,referenced_tweets,author_id,in_reply_to_user_id',
        'user.fields': 'username,name,profile_image_url,description',
        'media.fields': 'preview_image_url,url,type,width,height,variants',
        ...options,
    });
    return mapTweetResponseToLegacy(response);
};

const getUserTweets = (id: string, params?: Record<string, any>) => cacheTryGet(id, params, 'getUserTweets', (id, params = {}) => getUserTimeline(id, params, { exclude: 'replies' }));

View on GitHub (pinned to bed535e087)