{"record":{"id":"6c5b993d112f8b46","repo":"jackwener/OpenCLI","slug":"no-live-streams-returned-suffix","errorCode":null,"errorMessage":"No live streams returned${suffix}","messagePattern":"No live streams returned(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clis/tiktok/live.js","lineNumber":98,"sourceCode":"      for (const entry of list) {\n        const row = normalizeLiveItem(entry, dedup.size + 1);\n        if (row) {\n          const key = row.streamer || row.url;\n          if (key && !dedup.has(key)) dedup.set(key, row);\n        }\n      }\n    } catch (error) {\n      apiFailure = error instanceof Error ? error.message : String(error);\n    }\n  }\n\n  const rows = Array.from(dedup.values())\n    .slice(0, limit)\n    .map((row, index) => ({ ...row, index: index + 1 }));\n\n  if (rows.length === 0) {\n    const suffix = apiFailure ? ' (live-discover API failed: ' + apiFailure + ')' : '';\n    throw new Error('No live streams returned' + suffix);\n  }\n  return rows;\n})()\n`;\n}\n\nasync function listLive(page, args) {\n    const limit = requireLimit(args.limit, { fallback: DEFAULT_LIMIT, max: MAX_LIMIT });\n    await page.goto('https://www.tiktok.com/live', { waitUntil: 'load', settleMs: 5000 });\n    let rows;\n    try {\n        rows = await page.evaluate(buildLiveScript(limit));\n    } catch (error) {\n        throwTikTokPageContextError(error, {\n            authMessage: 'TikTok requires browser access to load live streams',\n            emptyPattern: /No live streams returned/,\n            emptyTarget: 'tiktok live',\n            failureMessage: 'Failed to load TikTok live streams',","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/tiktok/live.js#L80-L116","documentation":"The live command collects live streams via TikTok's live-discover API; if zero unique rows are gathered, the script throws 'No live streams returned'. An API failure on the pages is appended as '(live-discover API failed: ...)' so the caller can tell an API breakdown from genuinely no live streams.","triggerScenarios":"The live-discover endpoint returned an empty list for the queried scope; the first page fetch failed (assertTikTokApiSuccess or fetchJson error) setting apiFailure; msToken/signature missing causing rejected requests.","commonSituations":"Region where TikTok Live discovery returns nothing; no live streams matching the current query at that moment; TikTok rate-limiting live-discover from automated traffic; signed-request failures due to missing msToken cookie.","solutions":["Read the '(live-discover API failed: ...)' suffix to diagnose the underlying API error.","Refresh cookies/msToken and retry — live discovery endpoints are strict about signed requests.","Retry later; live inventory changes minute to minute, so an empty result may be transient.","Confirm in a browser that tiktok.com/live shows streams for your region/account.","If truly no streams exist for the query, catch this error and handle it as an empty list."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isLiveEmpty(e) {\n  return e instanceof Error && e.message.startsWith('No live streams returned');\n}\nfunction hadApiFailure(e) { return /live-discover API failed:/.test(e?.message || ''); }","tryCatchPattern":"try {\n  rows = await liveCommand({ limit });\n} catch (e) {\n  if (isLiveEmpty(e)) {\n    if (hadApiFailure(e)) await sleep(30_000); // retry after API failure\n    else rows = []; // genuinely no live streams now\n  } else throw e;\n}","preventionTips":["Inspect the live-discover failure suffix to target the real cause","Keep msToken/session fresh — live endpoints reject unsigned requests","Retry later; live inventory is time-varying","Cross-check tiktok.com/live in a browser for the same region/session"],"tags":["tiktok","live","empty-result","api"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}