{"record":{"id":"066a668081a15da7","repo":"openclaw/openclaw","slug":"could-not-refresh-buzz-room-membership-for-chann","errorCode":null,"errorMessage":"Could not refresh Buzz room membership for ${channelId}","messagePattern":"Could not refresh Buzz room membership for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/buzz/src/room-membership-tracker.ts","lineNumber":213,"sourceCode":"      if (\n        refreshed.roles.get(params.botPublicKey) !== \"bot\" ||\n        !refreshed.members.has(params.botPublicKey)\n      ) {\n        blockedRooms.add(channelId);\n        throw new Error(`Buzz bot no longer has the Bot role in room ${channelId}`);\n      }\n      memberships.set(channelId, refreshed);\n      pendingMemberships.delete(channelId);\n      deniedMembers.delete(channelId);\n      blockedRooms.delete(channelId);\n      params.onMembershipsChanged?.(effectiveMemberships());\n      return;\n    }\n    if (state.generation !== state.lastAttemptedGeneration) {\n      return;\n    }\n    blockedRooms.add(channelId);\n    throw new Error(`Could not refresh Buzz room membership for ${channelId}`);\n  };\n\n  const refreshMembershipOnce = (channelId: string): Promise<void> => {\n    const current = refreshes.get(channelId);\n    if (current) {\n      current.generation += 1;\n      return current.promise;\n    }\n    const state = {\n      generation: 1,\n      lastAttemptedGeneration: 0,\n      promise: Promise.resolve(),\n    } satisfies RefreshState;\n    state.promise = refreshMembership(channelId, state).finally(() => {\n      if (refreshes.get(channelId) === state) {\n        refreshes.delete(channelId);\n      }\n      if (","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/buzz/src/room-membership-tracker.ts#L195-L231","documentation":"Thrown when all retry attempts in MEMBERSHIP_REFRESH_DELAYS_MS are exhausted for a channel and the refresh generation is still current (not superseded by a newer refresh). The room is marked blocked. It means the tracker could not obtain a valid, newer membership after every backoff delay.","triggerScenarios":"Relay repeatedly returns stale/pending membership, network errors during queryMembership across all retries, or the membership data never converges to a non-pending newer state within the configured delay schedule.","commonSituations":"Relay instability, transient query failures, relay serving cached pending state, or membership propagation lag longer than the total retry window.","solutions":["Check relay connectivity and queryMembership health for the channel.","Increase or extend MEMBERSHIP_REFRESH_DELAYS_MS if convergence is known to be slow.","Retry the refresh later via refreshMembershipOnce once the relay stabilizes.","Confirm the channel still exists and the bot still holds the Bot role upstream."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await refreshMembershipOnce(channelId);\n} catch (error) {\n  if (/Could not refresh Buzz room membership/.test(String(error))) {\n    await sleep(LONG_BACKOFF_MS);\n    void refreshMembershipOnce(channelId);\n    return;\n  }\n  throw error;\n}","preventionTips":["Monitor relay query latency and membership convergence times.","Tune MEMBERSHIP_REFRESH_DELAYS_MS to the relay's observed propagation lag.","Alert when rooms become blocked so operators can investigate the relay."],"tags":["retry","network","buzz","room-membership","timeout"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}