jackwener/OpenCLI · warning · EmptyResultError

TikTok returned no live streams

Error message

TikTok returned no live streams

What it means

listLive's final guard: after the page script returns, if rows is not a non-empty array the library throws EmptyResultError('tiktok live', 'TikTok returned no live streams'). It guarantees a typed empty-result error rather than returning an empty success value.

Source

Thrown at clis/tiktok/live.js:120

`;
}

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

export const liveCommand = cli({
    site: 'tiktok',
    name: 'live',
    access: 'read',
    description: 'Browse TikTok live streams via page-context APIs',
    domain: 'www.tiktok.com',
    strategy: Strategy.COOKIE,
    browser: true,
    args: [
        { name: 'limit', type: 'int', default: DEFAULT_LIMIT, help: `Number of streams (max ${MAX_LIMIT})` },
    ],
    columns: ['index', 'streamer', 'name', 'title', 'viewers', 'likes', 'secUid', 'url'],
    func: listLive,
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Catch EmptyResultError and treat it as an empty stream list.
  2. Retry later — live availability is highly time-dependent.
  3. Verify tiktok.com/live renders streams in a browser for the same session to rule out region/session issues.
  4. Upgrade the library if TikTok changed the live-discover response shape.
  5. Check for rate limiting or bot-walls if the empty result is persistent.

Example fix

// before
const rows = await liveCommand({ limit: 20 });
// after
try {
  rows = await liveCommand({ 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 liveCommand({ limit });
} catch (e) {
  if (e instanceof EmptyResultError) rows = [];
  else throw e;
}

Prevention

When it happens

Trigger: The injected script returned null/undefined or an empty array — live-discover produced zero streams or the response shape changed so no rows were normalized.

Common situations: No live streams available in the account's region at query time; TikTok A/B changes to the live-discover payload breaking the normalizer; upstream API degraded to empty payloads.

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/114c87cd97e9d4cd. Report an issue: GitHub.