{"record":{"id":"a3b7af8fa80513e2","repo":"block/buzz","slug":"could-not-load-active-huddles-pagination-cursor-d","errorCode":null,"errorMessage":"Could not load active huddles: pagination cursor did not advance.","messagePattern":"Could not load active huddles: pagination cursor did not advance\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"desktop/src/features/huddle/lib/huddlePresence.ts","lineNumber":240,"sourceCode":"      ],\n      ...(channelIds?.length ? { \"#h\": channelIds } : {}),\n      ...(until === undefined ? {} : { until }),\n      limit: HUDDLE_LIFECYCLE_PAGE_LIMIT,\n      ...(beforeId === undefined ? {} : { before_id: beforeId }),\n    });\n    for (const event of page) events.set(event.id, event);\n    if (page.length < HUDDLE_LIFECYCLE_PAGE_LIMIT) break;\n\n    const terminal = [...page]\n      .sort((left, right) =>\n        left.created_at !== right.created_at\n          ? right.created_at - left.created_at\n          : left.id.localeCompare(right.id),\n      )\n      .at(-1);\n    if (!terminal) break;\n    if (until === terminal.created_at && beforeId === terminal.id) {\n      throw new Error(\n        \"Could not load active huddles: pagination cursor did not advance.\",\n      );\n    }\n    until = terminal.created_at;\n    beforeId = terminal.id;\n  }\n\n  return [...events.values()];\n}\n\n/** Incremental, bounded reconstruction of authenticated active huddles. */\nexport class HuddlePresenceTracker {\n  private readonly relaySelf: string;\n  private readonly sessions = new Map<string, HuddleSession>();\n\n  constructor(relaySelfPubkey: string | null | undefined) {\n    this.relaySelf = normalizePubkey(relaySelfPubkey ?? \"\");\n  }","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/block/buzz/blob/dad5a33865fc81a2e55b3b60746632f615ec1e3a/desktop/src/features/huddle/lib/huddlePresence.ts#L222-L258","documentation":"fetchHuddleLifecycleHistory pages backward through huddle lifecycle history with a (until, beforeId) cursor. If a full page's terminal (oldest) event is identical to the current cursor, pagination can never advance and the loop would spin forever, so it throws this error as a safety valve.","triggerScenarios":"The relay returns a page whose oldest event equals the current cursor (same created_at and id), typically from a relay/DB that ignores or mishandles the 'until'/'before' filter bounds, or duplicate events across pages.","commonSituations":"Relay bug or older relay version that doesn't honor until/before filters; clock collisions where several events share created_at and the id tiebreak re-returns the same event; Postgres event-store ordering anomaly in the active-huddles query.","solutions":["Check the relay version honors NIP-01 'until' and 'before' filter parameters; upgrade the relay if pagination bounds are ignored.","Inspect the events around the cursor for duplicate ids/created_at values and correct the ordering tiebreak (id comparison) in the query.","Add a retry with a slightly adjusted cursor (e.g. until = terminal.created_at - 1) as a workaround for boundary ties.","Reproduce with a direct REQ using the failing cursor and compare returned page boundaries."],"exampleFix":"// before\nif (until === terminal.created_at && beforeId === terminal.id) {\n  throw new Error(\"Could not load active huddles: pagination cursor did not advance.\");\n}\n\n// after\nif (until === terminal.created_at && beforeId === terminal.id) {\n  // one-time boundary nudge for ties, then fail if still stuck\n  if (!nudged) { nudged = true; until = terminal.created_at - 1; beforeId = undefined; continue; }\n  throw new Error(\"Could not load active huddles: pagination cursor did not advance.\");\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const huddles = await fetchHuddleLifecycleHistory(args);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"pagination cursor did not advance\")) {\n    logger.warn(\"huddle history pagination stalled; rendering partial history\", e);\n    return partialResults; // degrade gracefully, don't block the UI\n  }\n  throw e;\n}","preventionTips":["Verify the relay honors until/before filter bounds before relying on backward pagination.","Always break ties with a unique id ordering alongside created_at.","Cap total pages and detect non-advancing cursors early in any pagination loop.","Add tests that page through duplicate-timestamp event sets."],"tags":["pagination","relay","huddle","infinite-loop-guard"],"backgroundTag":"pagination-cursor-not-advancing","analyzedSha":"dad5a33865fc81a2e55b3b60746632f615ec1e3a","analyzedAt":"2026-09-05T18:13:50.666Z","contentChangedAt":"2026-09-05T18:13:50.666Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}