Documentation Index
Fetch the complete documentation index at: https://mintlify.com/betterdiscord/betterdiscord/llms.txt
Use this file to discover all available pages before exploring further.
BetterDiscord includes several built-in debugging tools and developer features to help you troubleshoot issues.
Developer settings
Enable developer features in BetterDiscord settings under Settings > BetterDiscord > Developer.
Debugger hotkey
Press F7 or F8 to trigger a debugger breakpoint:
// When F7/F8 is pressed, execution pauses here
function myFunction() {
const data = processData();
// Debugger will pause, allowing inspection
return data;
}
This is useful for:
- Pausing execution at specific moments
- Inspecting Discord’s internal state
- Debugging race conditions
- Examining call stacks
Inspect element hotkey
Press Ctrl+Shift+C (Windows/Linux) or Cmd+Shift+C (macOS) to open DevTools and inspect an element.
This opens the element picker, allowing you to:
- Inspect element HTML structure
- View React props and state
- Examine computed styles
- Find element selectors for CSS
Enable React DevTools to inspect React components:
- Enable in BetterDiscord settings
- Restart Discord
- Open DevTools (Ctrl+Shift+I)
- Use the Components and Profiler tabs
React DevTools requires a Discord restart to activate or deactivate.
Debug logs
Enable debug logging to record all console output to a file:
Location: %appdata%/BetterDiscord/debug.log (Windows)
~/Library/Application Support/BetterDiscord/debug.log (macOS)
~/.config/BetterDiscord/debug.log (Linux)
The debug log includes:
- All console.log, console.warn, console.error output
- Timestamps for each entry
- Stack traces for errors
Use debug logs to:
- Capture errors that happen quickly
- Share logs when reporting issues
- Track plugin behavior over time
- Debug issues that are hard to reproduce
Debug logs can grow very large (100MB+). BetterDiscord will prompt you to delete the log if it exceeds 100MB.
Console debugging
Basic logging
Use console methods to debug your code:
console.log("Basic log message");
console.info("Info message");
console.warn("Warning message");
console.error("Error message");
console.debug("Debug message");
Structured logging
Log objects and data structures:
const data = { user: "John", id: 123 };
// Log object
console.log("User data:", data);
// Log as table
console.table(data);
// Log with formatting
console.log("%cStyled log", "color: red; font-size: 16px;");
Stack traces
Print stack traces to see where code is called from:
console.trace("Function called from:");
function debugFunction() {
console.trace("Call stack:");
}
Timing operations
Measure execution time:
console.time("Operation");
// Your code here
for (let i = 0; i < 1000000; i++) {
// Do something
}
console.timeEnd("Operation"); // Operation: 45.123ms
Assertions
Test conditions and log when they fail:
const value = 5;
console.assert(value > 10, "Value should be greater than 10", value);
// Logs error if assertion fails
- Windows/Linux:
Ctrl+Shift+I
- macOS:
Cmd+Option+I
- Or: Right-click > Inspect Element
Breakpoints
Set breakpoints in the Sources tab:
- Open DevTools
- Navigate to Sources tab
- Find your plugin file
- Click the line number to add a breakpoint
- Code will pause when that line executes
Conditional breakpoints
Right-click a line number and choose “Add conditional breakpoint”:
// Breakpoint only triggers when condition is true
function processMessage(message) {
// Conditional breakpoint: message.author.id === "123456789"
console.log(message);
}
Watch expressions
Monitor values while debugging:
- Pause at a breakpoint
- In the Watch panel, click +
- Enter an expression (e.g.,
this.props.message)
- Value updates as you step through code
Call stack
View the call stack in the Call Stack panel:
function a() { b(); }
function b() { c(); }
function c() { debugger; }
a();
// Call stack shows: c > b > a
Scope inspection
Inspect variables in the Scope panel:
- Local variables
- Closure variables
- Global variables
BdApi debugging
Test patches
Verify patches are applied:
const patches = BdApi.Patcher.getPatchesByCaller("MyPlugin");
console.log("Active patches:", patches.length);
for (const patch of patches) {
console.log("Patch:", patch);
}
Test webpack searches
Debug module searches:
const filter = BdApi.Webpack.Filters.byKeys("sendMessage");
const modules = BdApi.Webpack.getModules(filter);
console.log("Found modules:", modules.length);
modules.forEach((m, i) => {
console.log(`Module ${i}:`, Object.keys(m));
});
Inspect webpack modules
Explore all webpack modules:
// Get all module IDs
const ids = Object.keys(BdApi.Webpack.modules);
console.log("Total modules:", ids.length);
// Find modules containing specific code
for (const id of ids) {
const module = BdApi.Webpack.getById(id);
if (module?.exports?.sendMessage) {
console.log("Found sendMessage in module:", id);
}
}
Check settings
Verify plugin settings:
const settings = BdApi.Data.load("MyPlugin", "settings");
console.log("Current settings:", settings);
Common issues
Plugin not loading
Check the console for errors:
- Open DevTools
- Look for red error messages
- Check if your plugin name appears
Common causes:
- Syntax errors
- Missing meta information
- Missing return statement in plugin class
Patches not working
Verify the target still exists:
const module = BdApi.Webpack.getByKeys("targetFunction");
if (!module) {
console.error("Module not found - Discord may have changed");
return;
}
console.log("Module found:", module);
console.log("Function exists:", typeof module.targetFunction);
React errors
Check for common React issues:
// Verify component exists
const Component = BdApi.Webpack.getByDisplayName("MessageContent");
console.log("Component:", Component);
// Check if it's a valid React element
const element = BdApi.React.createElement(Component, {});
console.log("Valid element:", BdApi.React.isValidElement(element));
Memory leaks
Check for memory leaks:
- Open DevTools > Memory tab
- Take a heap snapshot
- Enable/disable your plugin
- Take another snapshot
- Compare snapshots
Common causes:
- Not unpatching when plugin stops
- Event listeners not removed
- Circular references
- Storing large objects
Error handling
Try-catch blocks
Wrap risky code in try-catch:
start() {
try {
this.patchMessages();
} catch (error) {
console.error("Failed to patch messages:", error);
BdApi.showToast("MyPlugin failed to start", { type: "error" });
}
}
Patch error handling
Handle errors in patches:
BdApi.Patcher.after("MyPlugin", module, "render", (thisObject, args, returnValue) => {
try {
// Your modifications
returnValue.props.custom = true;
return returnValue;
} catch (error) {
console.error("Patch failed:", error);
// Return unmodified value
return returnValue;
}
});
Global error handler
Catch unhandled errors:
module.exports = class MyPlugin {
start() {
window.addEventListener("error", this.handleError);
}
stop() {
window.removeEventListener("error", this.handleError);
}
handleError = (event) => {
if (event.error?.stack?.includes("MyPlugin")) {
console.error("MyPlugin error:", event.error);
event.preventDefault();
}
}
}
Profile rendering
Use React DevTools Profiler:
- Enable React DevTools
- Open DevTools > Profiler tab
- Click Record
- Perform actions
- Stop recording
- Analyze render times
Measure patch impact
Time your patches:
BdApi.Patcher.after("MyPlugin", module, "render", (thisObject, args, returnValue) => {
const start = performance.now();
// Your modifications
returnValue.props.custom = true;
const duration = performance.now() - start;
if (duration > 5) {
console.warn(`Patch took ${duration}ms`);
}
return returnValue;
});
Monitor memory usage
Check memory usage:
if (performance.memory) {
console.log("Used JS heap:",
(performance.memory.usedJSHeapSize / 1048576).toFixed(2), "MB"
);
console.log("Total JS heap:",
(performance.memory.totalJSHeapSize / 1048576).toFixed(2), "MB"
);
}
Best practices
- Enable debug logs when developing
- Use descriptive console messages
- Remove debug code before releasing
- Handle all errors gracefully
- Test with DevTools open
- Use React DevTools for component issues
- Profile performance-critical code
- Check for memory leaks
- Test with other plugins enabled
Always test your plugin with debug logs enabled and DevTools open during development.