Skip to content
Fluxer API

Opcodes and close codes

Every Gateway payload has an opcode, and the Gateway ends a connection with a close code.

OpNameDescription
0DispatchServer to client. An event with its name in t and a sequence in s
1HeartbeatBoth ways. The client sends its last sequence or null in d. Answer a server heartbeat at once
2IdentifyClient to server. Starts a session with an Identify object
3Presence UpdateClient to server. A Presence Update object
4Voice State UpdateClient to server. A Voice State Update object
5Voice Server PingReserved. The Gateway closes a client that sends it
6ResumeClient to server. Restores a session with a Resume object
7ReconnectServer to client, with no d, before a close with 4000. Reconnect and resume
8Request Guild MembersClient to server. A Request Guild Members object
9Invalid SessionServer to client, always with d: false. Start a new session with Identify
10HelloServer to client, with heartbeat_interval, as soon as the WebSocket opens
11Heartbeat ACKServer to client, with no d, for each accepted heartbeat
12Gateway ErrorServer to client. A refused voice join
13Voice SignalClient to server. A Voice Signal object for one other voice connection
14Lazy RequestClient to server. A Lazy Request object
15Request Guild CountsClient to server. A Request Guild Counts object
16Request Channel Member CountsClient to server. A Request Channel Member Counts object
28Request Forum UnreadsClient to server. A Request Forum Unreads object

Ignore a server opcode that isn’t in this table.

Opcode 12 tells the session that sent a Voice State Update that the join was refused. It has no s or t, and the connection stays open.

FieldTypeDescription
codestringThe refusal code
messagestringA readable description for logs
{
"op": 12,
"d": {
"code": "VOICE_P2P_CONSENT_REQUIRED",
"message": "This call is peer-to-peer and requires agreement to join"
}
}

The Gateway sends three codes.

  • VOICE_P2P_CONSENT_REQUIRED means the call is peer-to-peer and the join didn’t send p2p: true. Ask the user, then join again with p2p: true. Peer-to-peer voice has the flow.
  • VOICE_P2P_UNAVAILABLE means the Gateway declined peer-to-peer for this join. Abort the join and tell the user.
  • VOICE_CHANNEL_FULL means the channel is at its user_limit or the peer-to-peer call is full. Abort the join and tell the user.

Other refused voice joins get no opcode 12.

CodeNameMeaning
4000Unknown errorThe node is draining, session creation failed, or the session in Resume did not answer
4001Unknown opcodeAn undefined or Gateway-only opcode, a payload with no d, or opcode 28 without thread access or an object d
4002Decode errorThe payload size, compression, encoding or command fields are invalid
4003Not authenticatedA command arrived before Identify or Resume attached a session
4004Authentication failedThe token is invalid, or it doesn’t own the session in Resume
4005Already authenticatedIdentify or Resume arrived while a session was attached, or with no d
4007Invalid sequenceHeartbeat d isn’t an integer or null, or Resume seq is out of range
4008Rate limitedA connection, payload, source IP or session budget was exceeded
4009Session timeoutNo heartbeat was accepted for 45,000 ms
4010Invalid shardThe Identify shard isn’t a valid [shard_id, shard_count] pair1
4011Sharding requiredMore than 2,500 guilds belong to one bot session2
4012Invalid API versionThe v connection parameter is missing or isn’t 1

1 shard_count is 1 to 16384 and shard_id is a non-negative integer below it

2 The Gateway counts guilds after the shard filter. Raise shard_count until each shard has at most 2,500.

If the connection had a session, you can Resume it for 60,000 ms after any close, including a network failure or a normal 1000 or 1001 close. When a Resume closes with 4004 or 4007, the session stays and you can try again. Resume only replays events still in the replay buffer.

Change the token, shard pair or version before you reconnect after 4004, 4010 or 4012.

Heartbeat closes with 4007 only after a session is attached.

Resume closes with 4007 when seq is above the last sequence the session dispatched or below the last acknowledged sequence. A seq inside those bounds but older than the oldest event in the replay buffer gets opcode 9 with d: false, and the session stays available.

Every close with a 4000-range code has a reason. Branch on the code and log the reason. The reasons below say more than their code. Other codes use the close code name as the reason.

ReasonCodeCause
Failed to start session4000Session creation failed for an unclassified reason
Session unavailable4000The session did not answer during Resume
Session drain requested; reconnect to continue4000Opcode 7 came just before the close
Encode failed4002Hello could not be encoded
Compression failed: zstd-stream4002Hello could not be compressed on a zstd connection
Payload too large4002A message is over 16,384 bytes, on the wire or after decompression
Decompression failed4002A compressed message could not be decompressed
Decode failed4002The payload isn’t valid JSON or isn’t an object
Invalid payload4002The decoded object has no op
Invalid identify payload4002Identify is missing token or properties, or a field has the wrong type
Invalid resume payload4002Resume is missing token, session_id or an integer seq, or a field has the wrong type
Invalid presence payload4002Presence Update is not an object or has no valid status
Invalid voice payload4002Voice State Update d is not an object
Invalid token4004The Identify token is invalid or the Resume token doesn’t own the session
Too many connections4008The source IP has 256 concurrent connections
Rate limited4008The connection, source IP or user payload budget was exceeded
Too many sessions4008The user already has 100 live sessions, which doesn’t apply to bots
Identify rate limited4008The instance is starting too many sessions at once, so try Identify again after a backoff
Resume rate limited4008The instance is resuming too many sessions at once, so try Resume again after a backoff
Heartbeat timeout4009No heartbeat was accepted for 45,000 ms

The Gateway drops some over-budget commands, such as Presence Update and Voice Signal, without closing the connection.