block/buzz · error · Error
Could not load active huddles: pagination cursor did not adv
Error message
Could not load active huddles: pagination cursor did not advance.
What it means
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.
Source
Thrown at desktop/src/features/huddle/lib/huddlePresence.ts:240
],
...(channelIds?.length ? { "#h": channelIds } : {}),
...(until === undefined ? {} : { until }),
limit: HUDDLE_LIFECYCLE_PAGE_LIMIT,
...(beforeId === undefined ? {} : { before_id: beforeId }),
});
for (const event of page) events.set(event.id, event);
if (page.length < HUDDLE_LIFECYCLE_PAGE_LIMIT) break;
const terminal = [...page]
.sort((left, right) =>
left.created_at !== right.created_at
? right.created_at - left.created_at
: left.id.localeCompare(right.id),
)
.at(-1);
if (!terminal) break;
if (until === terminal.created_at && beforeId === terminal.id) {
throw new Error(
"Could not load active huddles: pagination cursor did not advance.",
);
}
until = terminal.created_at;
beforeId = terminal.id;
}
return [...events.values()];
}
/** Incremental, bounded reconstruction of authenticated active huddles. */
export class HuddlePresenceTracker {
private readonly relaySelf: string;
private readonly sessions = new Map<string, HuddleSession>();
constructor(relaySelfPubkey: string | null | undefined) {
this.relaySelf = normalizePubkey(relaySelfPubkey ?? "");
}View on GitHub (pinned to dad5a33865)
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.
Example fix
// before
if (until === terminal.created_at && beforeId === terminal.id) {
throw new Error("Could not load active huddles: pagination cursor did not advance.");
}
// after
if (until === terminal.created_at && beforeId === terminal.id) {
// one-time boundary nudge for ties, then fail if still stuck
if (!nudged) { nudged = true; until = terminal.created_at - 1; beforeId = undefined; continue; }
throw new Error("Could not load active huddles: pagination cursor did not advance.");
} Defensive patterns
Strategy: retry
Try / catch
try {
const huddles = await fetchHuddleLifecycleHistory(args);
} catch (e) {
if (e instanceof Error && e.message.includes("pagination cursor did not advance")) {
logger.warn("huddle history pagination stalled; rendering partial history", e);
return partialResults; // degrade gracefully, don't block the UI
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Thread fetch completed but expected event ${expectedEventId}
- an admin cannot ban or time out a community owner or fellow
- BUZZ_RELAY_PRIVATE_KEY must be set when BUZZ_REQUIRE_AUTH_TO
- failed to sign member snapshot: {error}
- repo announcement rejected by community deletion fence: {e}
AI-assisted analysis of block/buzz@dad5a33865 (2026-09-05).
Data as JSON: /api/errors/a3b7af8fa80513e2.
Report an issue: GitHub.