openclaw/openclaw · error · Error

Missing Buzz room membership for ${channelId}

Error message

Missing Buzz room membership for ${channelId}

What it means

Thrown inside refreshMembership when the baseline membership for a channelId is absent from the memberships map. refreshMembership is only valid for channels already seeded with an initial membership; calling it for an unseeded or evicted channel is an internal invariant violation.

Source

Thrown at extensions/buzz/src/room-membership-tracker.ts:161

        await queryBuzzRoomMemberships({
          relay: params.relay,
          relayPublicKey: params.relayPublicKey,
          channelIds: [channelId],
          signal: params.signal,
        })
      ).get(channelId),
    );
    membershipQueryTail = query.then(
      () => undefined,
      () => undefined,
    );
    return query;
  };

  const refreshMembership = async (channelId: string, state: RefreshState): Promise<void> => {
    const baseline = memberships.get(channelId);
    if (!baseline) {
      throw new Error(`Missing Buzz room membership for ${channelId}`);
    }
    for (const delayMs of MEMBERSHIP_REFRESH_DELAYS_MS) {
      const generation = state.generation;
      state.lastAttemptedGeneration = generation;
      await sleepWithSignal(delayMs, params.signal);
      if (state.generation !== generation) {
        continue;
      }
      let refreshed: BuzzRoomMembership | undefined;
      try {
        refreshed = await queryMembership(channelId);
      } catch (error) {
        if (params.signal?.aborted) {
          throw error;
        }
        continue;
      }
      if (state.generation !== generation || !refreshed) {

View on GitHub (pinned to 01804a7531)

Solutions

  1. Ensure initial memberships for all configured channelIds are loaded before scheduling refreshes.
  2. Guard refresh scheduling against rooms removed from the active configuration.
  3. Treat a missing baseline as a no-op (skip refresh) rather than throwing if the room is no longer configured.

Example fix

// before
const baseline = memberships.get(channelId);
if (!baseline) {
  throw new Error(`Missing Buzz room membership for ${channelId}`);
}

// after - skip refresh for unseeded/evicted rooms
const baseline = memberships.get(channelId);
if (!baseline) {
  return; // room no longer tracked; nothing to refresh
}
Defensive patterns

Strategy: validation

Validate before calling

function hasBaselineMembership(
  memberships: Map<string, unknown>,
  channelId: string,
): boolean {
  return memberships.has(channelId);
}

if (!hasBaselineMembership(memberships, channelId)) {
  // seed membership or skip refresh
}

Prevention

When it happens

Trigger: refreshMembership invoked for a channelId whose membership was never loaded, was deleted, or whose initial load failed before refresh started. Indicates a lifecycle/ordering bug in the tracker rather than user input.

Common situations: A race where a room is removed from the configured set concurrently with a pending refresh, or a prior startup failure left the memberships map partially populated.

Related errors


AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12). Data as JSON: /api/errors/8c1a980130b13280. Report an issue: GitHub.