Client has two on-demand server reads. fetchRoles() returns the server’s roles, and it works. fetchMembers() returns the member roster, and it is currently out of service. Neither read caches, so each call goes to the server and gives you a point-in-time answer.
Fetch the roles
client.fetchRoles(serverId) returns a Promise<Role[]>. It reads on demand and does not cache.
string
The role’s id.
string
The role’s name.
string | null
The role’s primary color, or
null if none is set.string | null
The role’s secondary color, or
null if none is set.number | null
The role’s position, or
null if unknown. Lower is higher in the list.number
How many members hold this role.
A !roles command
fetchRoles() is a server read, so guard the handler first. Message.serverId is string | null and is null for a direct message, which arrives on the same messageCreate event.
msg.channel.send(), a plain send. msg.reply() would post a true reply with a quote header and fire a “replied to you” notification, which is more than a command answer needs.
msg.channel.send() is fire-and-forget. Its promise resolves when the frame leaves the process, not when the server accepts it. A server-side denial arrives later on the sendRejected event, so listen for that if you need to know a send was refused.Counting members without fetchMembers()
Role.memberCount is the one live membership number a bot can read today. Summing it does not give you a server total, because a member holds at most one role and members with no role are counted nowhere, but it is enough for “how many people hold this role”.
messageCreate carries msg.authorId and msg.authorName, so a bot can build its own map of the people it has actually seen.
The member roster read
client.fetchMembers(serverId) is declared as Promise<Member[]>. Do not call it against a live server. See the warning at the top of this page: the call hangs rather than failing, so a bot that reaches it stalls the handler that awaited it.
The shape is documented here so code you write now still compiles once the read is rebuilt.
string
The member’s normalized id.
string
The member’s username.
number
An online-status code.
0 means offline.Date | null
When the account was created, when known. This is the account creation time, not the time the member joined this server.
null when unknown.string | null
The member’s icon, or
null if none is set.number | null
The member’s subscription tier, or
null if unknown.boolean
true if this member is a bot.MemberRole | null
The member’s assigned role, or
null if they have none. A MemberRole is { id, name, color, secondColor, admin }, where admin is true when the role carries admin.There is no live roster stream
These reads hit the server every time, so treat a result as a snapshot rather than a live view. Call again when you need current data. Cloak has no continuous member-roster feed for a bot. The firehose carries messages, not membership. The one inbound membership signal is thesystemMessage event with type: 'member_join', which fires when someone joins a server the bot is in.
SystemMessageEvent carries actorId, actorName, serverId, channelId, and an optional groupId resolved from the bot’s channel-group cache. Pass groupId through in SendOptions so the send does not have to guess the channel’s group.
The voice roster events are a separate thing and are not a firehose either. They reach a bot only for the server it currently has selected or is in voice in, so they are not a general membership feed.
Read through the guild() handle
Both reads are bound on theguild() handle when you already have one for the server.
Handle failures
fetchRoles() rejects with a CloakActionError when the server refuses the read or errors while serving it. Wrap it and decide what to do when the roles are not available.
fetchMembers() has no working failure path today. It does not reject, so the catch above would never run for it.
Next
Types
Every field on Role, Member, and MemberRole.
Known limitations
What else is out of service, and what is tracked.
The guild() handle
The other way to reach these reads.
Moderation
Act on a member once you have their id.