How to Enable and Use Debug Logging in Baileys to Troubleshoot WhatsApp Connection Issues
To enable debug logging in Baileys, inject a custom Pino logger with level: 'debug' into makeWASocket() via the logger option—this exposes detailed protocol-level diagnostics from connection handling, message processing, and media operations.
Baileys, the popular WhatsApp Web API library, uses structured logging throughout its codebase to help developers diagnose connection problems, message delivery failures, and media handling errors. Understanding how to activate and leverage this debug logging is essential for production troubleshooting and development debugging. This guide shows you exactly how to configure debug logging in Baileys based on the actual source code implementation.
How Baileys Logging Works Under the Hood
Baileys uses Pino, a high-performance Node.js logger, as its standard logging infrastructure. The default logger is defined in [src/Utils/logger.ts](https://github.com/WhiskeySockets/Baileys/blob/master/src/Utils/logger.ts) and initializes at the info level, which suppresses debug messages.
When you create a Baileys socket with makeWASocket(), you can override this default by passing your own logger instance. The library propagates this logger to all sub-modules—including socket handling, message sending/receiving, and media processing—ensuring consistent, configurable logging across the entire stack.
Internal modules write debug logs using standard Pino calls like logger.debug({ data }, 'message'). With a properly configured logger, you'll see detailed information from these critical components:
- Connection lifecycle in
src/Socket/socket.ts— pre-key uploads, server time offsets, pairing steps - Incoming message handling in
src/Socket/messages-recv.ts— resend requests, MEX notifications, newsletter events - Outgoing message flow in
src/Socket/messages-send.ts— media fetches, receipt sends, device identity resolution - Media processing in
src/Utils/messages.tsandsrc/Utils/messages-media.ts— cache hits, thumbnail generation, upload progress - Event buffering in
src/Utils/event-buffer.ts— buffer activation, flushing, and destruction events
Method 1: Create and Inject a Debug Logger
The most direct way to enable debug logging in Baileys is to instantiate a Pino logger with debug level and pass it to your socket configuration.
import P from 'pino'
import makeWASocket, { useSingleFileAuthState } from '@whiskeySockets/baileys'
// Create a pino logger with debug level and custom timestamp
const logger = P({
level: 'debug',
timestamp: () => `,"time":"${new Date().toJSON()}"`
})
// Standard auth state setup
const { state, saveState } = useSingleFileAuthState('./baileys_auth_info.json')
// Initialize socket with the debug logger injected
const sock = makeWASocket({
logger, // <-- debug logging enabled
auth: state,
// additional options: version, printQRInTerminal, etc.
})
This pattern is validated in the test suite at [src/__tests__/e2e/helpers/test-client.ts](https://github.com/WhiskeySockets/Baileys/blob/master/src/__tests__/e2e/helpers/test-client.ts), which demonstrates configurable logging levels for integration testing.
Method 2: Use Child Loggers for Contextual Debugging
For multi-session deployments or isolating specific conversations, use Pino's child loggers to inject context fields automatically into every log entry.
// Create a child logger bound to a specific chat
const chatLogger = logger.child({ chatId: '12345@s.whatsapp.net' })
sock.ev.on('messages.upsert', ({ messages }) => {
chatLogger.debug({ messages }, 'Received new messages')
})
Child loggers preserve the parent's level configuration while adding permanent context. This is invaluable when filtering logs by phone number, session ID, or chat identifier in centralized logging systems.
Method 3: Redirect Debug Logs to File
Production environments often require persistent debug logs rather than console output. Pipe your Pino logger to a file stream:
import fs from 'fs'
import P from 'pino'
const fileStream = fs.createWriteStream('./baileys-debug.log', { flags: 'a' })
const fileLogger = P(
{ level: 'debug' },
fileStream
)
const sock = makeWASocket({
logger: fileLogger,
auth: state
})
The flags: 'a' option enables append mode, preserving logs across restarts. Rotate this file externally or use Pino's transport features for production-grade log management.
Method 4: Enable Debug Logging via Environment Variable
For flexible deployment configurations without code changes, read the log level from an environment variable:
const logger = P({
level: process.env.LOG_LEVEL || 'info'
})
Then launch your application with debug logging activated:
LOG_LEVEL=debug node my-app.js
This approach lets you toggle debug visibility in containerized environments or CI/CD pipelines without rebuilding.
What Debug Logging Reveals: Key Diagnostic Areas
Once debug logging is active, you'll see structured JSON output detailing Baileys' internal operations. Here are the most valuable diagnostic categories:
Connection and Authentication Flows
- Server time synchronization offsets
- Pre-key bundle uploads and rotations
- QR code pairing progression
- WebSocket connection state transitions
Message Protocol Debugging
- Stanza parsing and validation
- Receipt acknowledgment sequences
- Retry and resend request handling
- Device list synchronization for multi-device accounts
Media Handling Diagnostics
- URL media fetch attempts and caching decisions
- Thumbnail generation parameters
- Encrypted upload progress and retry logic
- MIME type detection and conversion
Event System Internals
- Offline event buffering activation
- Buffer flush triggers and batching behavior
- Event deduplication and ordering guarantees
Summary
- Baileys uses Pino as its standard logger, defined in
src/Utils/logger.ts, with a default info level that hides debug messages - Inject a custom logger via
makeWASocket({ logger })usingP({ level: 'debug' })to expose diagnostic output - Child loggers add persistent context fields for multi-tenant or multi-session debugging
- File streams enable persistent logging suitable for production troubleshooting
- Environment variables allow runtime log level adjustment without code modification
- Debug output covers connection lifecycle, message protocols, media processing, and event buffering across multiple source files including
src/Socket/socket.ts,src/Socket/messages-recv.ts, andsrc/Utils/messages.ts
Frequently Asked Questions
What log levels does Baileys support?
Baileys supports all standard Pino log levels: trace, debug, info, warn, error, and fatal. Set level: 'trace' for maximum verbosity, though debug is typically sufficient for troubleshooting connection and message issues. The level hierarchy follows Pino's standard behavior—specifying a level includes all more severe levels.
Can I use a different logging library instead of Pino?
Yes, but your custom logger must implement Pino's API surface. The logger object passed to makeWASocket() is forwarded throughout the codebase to calls like logger.debug(), logger.info(), logger.warn(), and logger.child(). Any compatible logger implementing these methods will work, though Pino is recommended for performance and compatibility with Baileys' structured logging patterns.
Where are the most important debug logs located in the source?
The highest-value debug output originates from these files according to the Baileys source code:
src/Socket/socket.ts— connection establishment and WebSocket managementsrc/Socket/messages-recv.ts— inbound message and notification processingsrc/Socket/messages-send.ts— outbound message routing and delivery confirmationsrc/Utils/messages.ts— media preparation and caching logicsrc/Utils/event-buffer.ts— offline event queue behavior
Why am I not seeing debug output after setting the logger level?
Ensure you're passing the logger correctly to makeWASocket(), not just creating it. Verify the logger instance is used directly in the socket options object: { logger: myLogger, auth: state }. Also confirm no other code is overriding the level afterward, and check that your Pino version matches Baileys' dependency requirements.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →