jackwener/OpenCLI · warning · EmptyResultError

TikTok returned no following entries

Error message

TikTok returned no following entries

What it means

listFollowing's final safety net: even after the page script returns (or the page-context error mapper converts errors), if rows is not a non-empty array the library throws EmptyResultError('tiktok following', ...). It guarantees the command either returns real following rows or a typed empty-result error, never an empty success.

Source

Thrown at clis/tiktok/following.js:140

`;
}

async function listFollowing(page, args) {
    const limit = requireLimit(args.limit, { fallback: DEFAULT_LIMIT, max: MAX_LIMIT });
    await page.goto('https://www.tiktok.com/following', { waitUntil: 'load', settleMs: 5000 });
    let rows;
    try {
        rows = await page.evaluate(buildFollowingScript(limit));
    } catch (error) {
        throwTikTokPageContextError(error, {
            authMessage: 'TikTok requires login to read your following list',
            emptyPattern: /No following entries/,
            emptyTarget: 'tiktok following',
            failureMessage: 'Failed to load TikTok following list',
        });
    }
    if (!Array.isArray(rows) || rows.length === 0) {
        throw new EmptyResultError('tiktok following', 'TikTok returned no following entries');
    }
    return rows;
}

export const followingCommand = cli({
    site: 'tiktok',
    name: 'following',
    access: 'read',
    description: 'List accounts the logged-in user follows on TikTok via page-context APIs',
    domain: 'www.tiktok.com',
    strategy: Strategy.COOKIE,
    browser: true,
    args: [
        { name: 'limit', type: 'int', default: DEFAULT_LIMIT, help: `Number of accounts (max ${MAX_LIMIT})` },
    ],
    columns: ['index', 'username', 'name', 'secUid', 'verified', 'followers', 'following', 'url'],
    func: listFollowing,
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check whether the account follows anyone; if not, this is expected and you should catch EmptyResultError.
  2. Catch EmptyResultError and treat it as an empty list (rows = []) in your pipeline.
  3. Update/upgrade the library if TikTok changed the response shape (userList vs user_list) so the script repopulates rows.
  4. Re-run with a larger --limit or after re-logging in if it is transient.
  5. Inspect rows returned from page.evaluate to distinguish null (script error) vs [] (true empty).

Example fix

// before
const rows = await followingCommand({ limit: 20 });
// after
try {
  rows = await followingCommand({ limit: 20 });
} catch (e) {
  if (e instanceof EmptyResultError) rows = [];
  else throw e;
}
Defensive patterns

Strategy: try-catch

Type guard

function isEmptyResult(e) {
  return e instanceof EmptyResultError;
}

Try / catch

let rows = [];
try {
  rows = await followingCommand({ limit });
} catch (e) {
  if (e instanceof EmptyResultError) rows = [];
  else throw e;
}

Prevention

When it happens

Trigger: The injected script returned null/undefined (e.g. an earlier error path was swallowed), or returned an empty array because TikTok's API yielded zero entries for the viewer.

Common situations: Account genuinely follows no one; a regression in the page script causing a non-array return; upstream API degrading to empty payloads (TikTok A/B changes to the user/list response shape).

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/66c774136592ba67. Report an issue: GitHub.