Skip to main content

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

React DevTools

Enable React DevTools to inspect React components:
  1. Enable in BetterDiscord settings
  2. Restart Discord
  3. Open DevTools (Ctrl+Shift+I)
  4. 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

DevTools

Opening DevTools

  • Windows/Linux: Ctrl+Shift+I
  • macOS: Cmd+Option+I
  • Or: Right-click > Inspect Element

Breakpoints

Set breakpoints in the Sources tab:
  1. Open DevTools
  2. Navigate to Sources tab
  3. Find your plugin file
  4. Click the line number to add a breakpoint
  5. 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:
  1. Pause at a breakpoint
  2. In the Watch panel, click +
  3. Enter an expression (e.g., this.props.message)
  4. 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:
  1. Open DevTools
  2. Look for red error messages
  3. 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:
  1. Open DevTools > Memory tab
  2. Take a heap snapshot
  3. Enable/disable your plugin
  4. Take another snapshot
  5. 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();
        }
    }
}

Performance debugging

Profile rendering

Use React DevTools Profiler:
  1. Enable React DevTools
  2. Open DevTools > Profiler tab
  3. Click Record
  4. Perform actions
  5. Stop recording
  6. 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.