Skip to main content
Debugging a hosted application requires you to capture runtime information that is normally invisible during production execution. Virtus Cloud surfaces all stdout and stderr output in the application logs panel, which means any debug information you write to the console becomes immediately visible without needing a local development environment. This guide shows you how to enable structured debug logging in both discord.js and discord.py so you can diagnose connection issues, API errors, and unexpected crashes directly from your dashboard.

Debugging a discord.js Application

The discord.js library exposes two key client events for debugging: debug and error. The debug event fires continuously with internal library information — gateway heartbeats, shard status, rate-limit notices, and more. The error event fires whenever the client encounters an unhandled error at the connection level. Register both listeners early in your bot’s startup sequence, before you call client.login():
const { Client, GatewayIntentBits } = require('discord.js');

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

// Fires with general internal library information
client.on('debug', (info) => {
    console.log(`Debug Info: ${info}`);
});

// Fires when the client encounters a connection-level error
client.on('error', (error) => {
    console.error(`Encountered an Error: ${error.message}`);
});

client.login(process.env.TOKEN);
The debug event is very verbose — it emits dozens of messages per minute during normal operation. Use it while diagnosing a specific issue, then remove or comment out the listener before deploying to production to keep your logs readable.
Once these listeners are in place, restart your application on Virtus Cloud and open the Logs panel in the dashboard. You will see a stream of debug output that includes gateway connection attempts, identify payloads, heartbeat acknowledgements, and any errors that occur during the session.
If your bot disconnects unexpectedly, look for rate-limit warnings (You are being rate limited) or reconnection attempts ([WS] Connection closed) in the debug output — these are the most common indicators of token or gateway issues.

Debugging a discord.py Application

The discord.py library integrates with Python’s standard logging module. By configuring a logger for the discord namespace, you gain visibility into every internal event the library processes — HTTP requests, gateway frames, heartbeats, and reconnection logic. Add the following logging setup at the top of your main file, before creating your bot client:
import logging
import logging.handlers

# Configure the root discord logger at DEBUG level
logger = logging.getLogger('discord')
logger.setLevel(logging.DEBUG)

# Reduce noise from the HTTP sub-module — INFO is sufficient
logging.getLogger('discord.http').setLevel(logging.INFO)

# Send all log output to the console (captured by Virtus Cloud logs)
handler = logging.StreamHandler()
dt_fmt = '%Y-%m-%d %H:%M:%S'
formatter = logging.Formatter(
    '[{asctime}] [{levelname:<8}] {name}: {message}',
    dt_fmt,
    style='{'
)
handler.setFormatter(formatter)
logger.addHandler(handler)

# Pass log_handler=None to prevent discord.py from adding its own handler
client.run("your token here", log_handler=None)
The log_handler=None argument passed to client.run() is important — without it, discord.py installs its own default handler and your log output may be duplicated or formatted inconsistently.
  • DEBUG — Every internal library event, including gateway frames and heartbeat payloads. Very verbose.
  • INFO — Higher-level events such as shard connections, login success, and guild loads.
  • WARNING — Non-fatal issues like rate limiting or missed heartbeats.
  • ERROR — Exceptions and failures that require attention.
  • CRITICAL — Fatal conditions that prevent the bot from running.
The discord.http sub-logger generates an entry for every API call your bot makes. Setting it to INFO suppresses individual request details while still surfacing HTTP errors (4xx/5xx responses). If you need to trace a specific API call, temporarily set it to DEBUG.
Never hardcode your bot token directly in your source file. Store it as an environment variable and reference it with os.environ["TOKEN"]. Committing a live token to version control exposes your bot to takeover.
After adding the logging configuration, redeploy your application and open the Logs panel in the Virtus Cloud dashboard. Every event the library processes will appear with a timestamp, log level, logger name, and human-readable message — giving you a complete picture of what your bot is doing at runtime.