DIYgod/RSSHub · warning · InvalidParameterError

This account doesn't exist

Error message

This account doesn't exist

What it means

Thrown by the getUser() helper in Twitter web-api when the GraphQL response has no userData.data.user object at all. This is a stronger failure than error 580 (which sees user but no rest_id): the API returned nothing for the account, so RSSHub rejects the request with InvalidParameterError("This account doesn't exist") before any tweet fetching is attempted.

Source

Thrown at lib/routes/twitter/api/web-api/api.ts:169

    gatherLegacyFromData(
        await paginationTweets(
            'ListLatestTweetsTimeline',
            undefined,
            {
                ...params,
                listId: id,
                count: 20,
            },
            ['list', 'tweets_timeline', 'timeline']
        ),
        ['listConversation-']
    );

const getUser = async (id: string) => {
    const userData: any = await getUserData(id);

    if (!userData.data.user) {
        throw new InvalidParameterError("This account doesn't exist");
    }
    if (userData.data.user.result.__typename === 'UserUnavailable') {
        throw new InvalidParameterError(userData.data.user.result.message || 'User is unavailable');
    }

    return {
        profile_image_url: userData.data?.user?.result?.avatar?.image_url,
        description: userData.data?.user?.result?.profile_bio?.description,
        ...userData.data?.user?.result?.core,
    };
};

const getHomeTimeline = async (id: string, params?: Record<string, any>) =>
    gatherLegacyFromData(
        await paginationTweets(
            'HomeTimeline',
            undefined,
            {

View on GitHub (pinned to bed535e087)

Solutions

  1. Confirm the handle exists by visiting https://x.com/<id> directly.
  2. Check server logs for 'twitter rate limit exceeded' / token-deletion messages; if all tokens are exhausted, add fresh TWITTER_AUTH_TOKEN values.
  3. Correct the route path typo or update to the current handle.
  4. Retry after the rate-limit lock window (cache key lockPrefix+token, TTL 2000s) expires if token exhaustion was the cause.
Defensive patterns

Strategy: validation

Validate before calling

async function accountResolves(handle: string): Promise<boolean> {
  const res = await fetch(`https://x.com/${handle}`, { method: 'HEAD', redirect: 'manual' });
  return res.status !== 404;
}

Type guard

function hasTwitterUserObject(userData: any): userData is { data: { user: object } } {
  return userData?.data?.user != null && typeof userData.data.user === 'object';
}

Try / catch

try { await fetchRss('/twitter/user/<handle>'); }
catch (e) {
  if (/doesn't exist/.test(String(e))) { /* drop feed, account is gone */ }
  else throw e;
}

Prevention

When it happens

Trigger: getUser(id) is invoked by routes that need profile metadata (lists, media, likes) and the underlying UserByRestId/UserByScreenName call returns a body whose data.user is absent. Happens with handles that never existed, accounts permanently deleted by Twitter, or when the token used is rate-limited into returning an empty data object.

Common situations: Typo in the route path; account was hard-deleted by Twitter (not just suspended); the active auth token was burned and Twitter returns {data:{}} for every user lookup, tripping the JSON.stringify === '{"user":{}}' rate-limit branch upstream while this guard fires first.

Related errors


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