{"record":{"id":"81d4c57d80b74d00","repo":"tonhowtf/omniget","slug":"tg-loadmedia-failed-in-performance-now-t0-tofixed-0-ms","errorCode":null,"errorMessage":"[TG] loadMedia failed in ${(performance.now() - t0).toFixed(0)}ms:","messagePattern":"\\[TG\\] loadMedia failed in (.+?)ms:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/study-components/TelegramBrowser.svelte","lineNumber":1560,"sourceCode":"        offset: reset ? 0 : mediaItems.length,\n        limit: PAGE_SIZE,\n      };\n      if (mediaFilter !== \"all\") args.mediaType = mediaFilter;\n      const fetchPromise = telegramListMedia(args);\n      const timeoutMs = 25_000;\n      const timeoutPromise = new Promise<TelegramMediaItem[]>((_, reject) =>\n        setTimeout(\n          () => reject(new Error(`telegram_list_media timeout (${timeoutMs}ms) — provavelmente FLOOD_WAIT, tente novamente em alguns segundos`)),\n          timeoutMs,\n        ),\n      );\n      const items = await Promise.race([fetchPromise, timeoutPromise]);\n      console.log(`[TG] loadMedia ok in ${(performance.now() - t0).toFixed(0)}ms, returned ${items.length} items`);\n      mediaItems = reset ? items : [...mediaItems, ...items];\n      mediaHasMore = items.length >= PAGE_SIZE;\n    } catch (e) {\n      const msg = e instanceof Error ? e.message : String(e);\n      console.warn(`[TG] loadMedia failed in ${(performance.now() - t0).toFixed(0)}ms:`, msg);\n      mediaError = msg;\n    } finally {\n      mediaLoading = false;\n    }\n  }\n\n  // F0.1 + F0.2: throttle + raf-batch for media thumbs\n  const thumbFetchLimit = makeLimit(4);\n  const pendingThumbUpdates = new Map<number, string>();\n  let thumbFlushScheduled = false;\n  function flushThumbUpdates() {\n    thumbFlushScheduled = false;\n    if (pendingThumbUpdates.size === 0) return;\n    const next = new Map(mediaThumbs);\n    for (const [k, v] of pendingThumbUpdates) next.set(k, v);\n    pendingThumbUpdates.clear();\n    mediaThumbs = next;\n  }","sourceCodeStart":1542,"sourceCodeEnd":1578,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src/lib/study-components/TelegramBrowser.svelte#L1542-L1578","documentation":"loadMedia() in TelegramBrowser.svelte fetches media items with a Promise.race against a timeout promise; on failure the catch logs '[TG] loadMedia failed in Nms:' with the error message and sets mediaError. The rejection comes either from the underlying fetch/IPC (TDPF/telegram media listing) or from the injected timeout promise, and the elapsed time is logged to help distinguish slow-but-successful calls from hard failures.","triggerScenarios":"The media fetch promise rejects (backend/IPC error while listing Telegram media) OR the timeout promise fires first because fetching exceeded the configured deadline; the resulting message is then stored in mediaError and rendered in the component.","commonSituations":"Slow Telegram API/media backend exceeding the page-load timeout on large galleries; network drop or paused backend while scrolling an infinite list; expired Telegram session/authorization causing the media query to reject; media service not running so the invoke fails immediately.","solutions":["Check the logged message and elapsed ms: near-zero ms means an immediate rejection (service/session issue); near the timeout value means a slow fetch.","Raise the timeout constant or increase PAGE_SIZE tuning if large pages legitimately exceed the deadline.","Verify the Telegram session/authorization is valid and the media backend service is reachable.","Add retry with exponential backoff for transient network failures before surfacing mediaError.","Ensure loadMedia is not re-entered while mediaLoading is true (concurrent calls can race and thrash)."],"exampleFix":"// before\nconst items = await Promise.race([fetchPromise, timeoutPromise]);\n// after\nlet attempt = 0;\nconst items = await (async () => {\n  while (attempt < 3) {\n    try {\n      return await Promise.race([fetchPromise, timeoutPromise]);\n    } catch (e) {\n      if (++attempt >= 3) throw e;\n      await new Promise((r) => setTimeout(r, 500 * attempt));\n    }\n  }\n})();","handlingStrategy":"retry","validationCode":"// before calling loadMedia\nif (mediaLoading) return; // prevent concurrent overlapping fetches\nif (!telegramSessionValid) { mediaError = 'Session expired'; return; }","typeGuard":"function isTimeoutError(e: unknown, elapsedMs: number, budgetMs: number): boolean {\n  if (!(e instanceof Error)) return String(e).includes('timeout');\n  return elapsedMs >= budgetMs - 50;\n}","tryCatchPattern":"try {\n  await loadMedia(reset);\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (msg.includes('timeout')) {\n    await retryWithBackoff(() => loadMedia(reset), 3);\n  } else {\n    mediaError = msg;\n  }\n}","preventionTips":["Never race a fetch without a deadline — always pair with a timeout promise like this code does","Log elapsed time to distinguish slow fetches from hard rejections","Reduce PAGE_SIZE if large pages routinely hit the timeout","Debounce infinite-scroll triggers so overlapping loadMedia calls cannot race","Validate Telegram session/auth before listing media to avoid immediate rejections"],"tags":["svelte","timeout","network","media-loading","telegram"],"backgroundTag":"request-timeout","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}