Why Discord Bot Voice Connection Disconnects After 2 Minutes Idle
🔍 WiseChecker

Why Discord Bot Voice Connection Disconnects After 2 Minutes Idle

If your Discord bot loses its voice connection after approximately two minutes of silence, you are encountering a built-in idle timeout enforced by Discord. This timeout is designed to free server resources when no audio data is being transmitted. The disconnection is not a bug or a hardware problem — it is a deliberate behavior of Discord’s voice gateway. This article explains the technical mechanism behind the 2-minute idle disconnect and provides concrete coding strategies to keep your bot connected.

Key Takeaways: Keeping Your Discord Bot Voice Channel Active

  • discord.py voice_client.idle_timeout: The internal timer that triggers disconnect after 120 seconds of silence.
  • discord.py VoiceClient.play() with silence audio: Sending a silent audio frame resets the idle timer without audible noise.
  • discord.js VoiceConnection.receiver.speaking.started event: A listener that can reset the idle timeout when users speak.

ADVERTISEMENT

Why Discord Disconnects Idle Bot Voice Connections After 2 Minutes

Discord’s voice infrastructure uses a WebSocket-based gateway to stream real-time audio. Each voice connection maintains a state machine that tracks whether audio is actively being sent or received. When no audio packets are transmitted for 120 seconds, Discord’s server closes the WebSocket connection with a specific close code (4015 for idle timeout). This behavior conserves bandwidth and processing power on Discord’s side, especially in large servers where many bots might otherwise hold open connections indefinitely.

The timeout applies to both user clients and bot accounts, but users rarely notice because they are usually in active conversation. Bots, however, often sit silently in a channel waiting for a command. The idle timer resets each time the bot sends an audio packet (even a silent one) or receives audio from another user. Simply being in the channel does not reset the timer — the bot must actively participate in the audio stream.

Technical Details of the Idle Timeout

The timeout is enforced at the Discord voice gateway level, not within the bot library. The relevant gateway opcode is Voice Speaking (opcode 5) and the Voice Heartbeat (opcode 3). Heartbeats keep the WebSocket alive but do not reset the idle timer. Only audio data (PCM frames) resets it. In discord.py, the VoiceClient object has an internal attribute idle_timeout (default 120 seconds) and a _idle_timer that triggers disconnect() when the timeout expires. In discord.js, the VoiceConnection emits a disconnect event with the reason idle.

Steps to Prevent Idle Disconnection in discord.py

The most reliable method is to send a silent audio frame at intervals shorter than 120 seconds. Below is a complete implementation using discord.py 2.x.

  1. Import required modules
    Add these imports at the top of your bot script: import discord, asyncio, struct, io. You need struct to build the silent PCM frame and io for the FFmpegPCMAudio source.
  2. Create a silent audio source
    Define a function that returns a discord.FFmpegPCMAudio object playing a silent WAV file. The simplest approach is to generate a 20-millisecond silent PCM frame in memory. Use discord.FFmpegPCMAudio(io.BytesIO(silent_wav_bytes)) where silent_wav_bytes is a valid WAV header plus 1764 bytes of zeros (44.1 kHz, 16-bit, mono).
  3. Start a background task to play silence
    After connecting to a voice channel, launch an asyncio.create_task that loops every 60 seconds. Inside the loop, call voice_client.play(silent_source). This resets the idle timer. The task should catch asyncio.CancelledError when the bot disconnects.
  4. Cancel the task on disconnect
    Override the on_voice_state_update event to detect when the bot leaves the channel. Cancel the background task using task.cancel() to avoid resource leaks.
  5. Test the connection
    Join a voice channel with your bot and wait 3 minutes. The bot should remain connected. Verify by checking the voice_client.is_connected() status.

ADVERTISEMENT

Steps to Prevent Idle Disconnection in discord.js

In discord.js, you can use the VoiceConnection receiver to detect when users speak and reset the timeout, or send silent frames using createAudioResource with a silent file.

  1. Install dependencies
    Ensure you have @discordjs/voice and ffmpeg-static installed. Run npm install @discordjs/voice ffmpeg-static.
  2. Create a silent audio resource
    Create a 20-millisecond silent WAV file using Node.js fs and child_process. Alternatively, use a pre-generated silent file in your project folder. Load it with createAudioResource('silence.wav').
  3. Play silence in a loop
    After joining a channel with joinVoiceChannel, use player.play(resource) inside a setInterval that runs every 60 seconds. Use player.stop() before playing to avoid overlapping audio.
  4. Clean up interval on disconnect
    Listen for the stateChange event on the VoiceConnection. When the status becomes VoiceConnectionStatus.Disconnected, clear the interval with clearInterval.

If the Bot Still Disconnects After Applying the Main Fix

Bot Disconnects Due to Network Latency Spikes

Even if you send silent frames, a sudden network issue can cause the WebSocket to close. Check your bot’s ping to Discord using voice_client.ping in discord.py or voiceConnection.ping in discord.js. If ping exceeds 500 ms, the gateway may disconnect. Use a server closer to Discord’s voice regions, or implement a reconnection loop that calls voice_client.connect() again.

Bot Disconnects After a Discord Update

Discord occasionally changes the idle timeout duration or the close code. In 2023, the timeout was reduced from 3 minutes to 2 minutes for some regions. Always check the Discord Developer Voice Connections documentation for the latest timeout values. Update your bot library to the latest version to handle any new close codes.

Bot Disconnects When No Users Are in the Channel

The idle timeout applies regardless of how many users are present. If your bot is alone in a channel, the same 2-minute rule applies. The silent frame method works here too. For bots that only need to listen for commands, consider using a text channel trigger and joining the voice channel only when needed, then leaving after the command finishes. This avoids the idle timeout entirely.

Comparison: Idle Timeout Workarounds for discord.py vs discord.js

Item discord.py discord.js
Silent frame method Use FFmpegPCMAudio with a silent WAV in memory Use createAudioResource with a silent file
Loop mechanism asyncio.create_task with while True and asyncio.sleep(60) setInterval with 60000 ms
Disconnect cleanup Catch on_voice_state_update and cancel task Listen to stateChange event and clear interval
Receiver-based reset Not natively supported; requires manual on_voice_state_update tracking Use VoiceConnection.receiver.speaking.started event
Library version tested discord.py 2.3.2 discord.js 14.14.1 with @discordjs/voice 0.17.0

Discord bots disconnect from voice channels after 2 minutes of idle activity due to a deliberate server-side timeout that conserves resources. You can prevent this by sending silent audio frames at regular intervals using the methods described above. For discord.py, use FFmpegPCMAudio with a silent WAV in a background task. For discord.js, use createAudioResource with a silent file in a setInterval. If the bot still disconnects, check network latency and update your library. A more advanced approach is to use the VoiceClient.reconnect() method to automatically rejoin the channel after an idle disconnect, though this may cause a brief interruption in audio.

ADVERTISEMENT