Overview
Debugging Dalamud plugins requires attaching to the game process. This guide covers debugging techniques, common issues, and best practices.Prerequisites:
- Visual Studio 2022, JetBrains Rider, or VS Code with C# debugger
- Your plugin built in Debug configuration
- FFXIV running with Dalamud
Attaching the Debugger
Visual Studio
Build in Debug Mode
Ensure your project is built in Debug configuration:Or select Debug from the configuration dropdown in Visual Studio.
Attach to Process
- In Visual Studio: Debug → Attach to Process (or
Ctrl+Alt+P) - In the process list, find
ffxiv_dx11.exe - Click Attach
JetBrains Rider
Configure Attach Settings
- Run → Edit Configurations
- Click + → Attach to Process
- Name it “Attach to FFXIV”
- Set the filter to “ffxiv_dx11.exe”
Visual Studio Code
Create alaunch.json configuration:
.vscode/launch.json
- Press
F5or Run → Start Debugging - Select “Attach to FFXIV”
Debug Configuration
Optimize your.csproj for debugging:
.csproj
- Full debug symbols are generated
- Optimizations are disabled (easier to debug)
DEBUGconstant is defined
Debugging Techniques
Conditional Breakpoints
Break only when specific conditions are met:- Right-click a breakpoint
- Select Conditions
- Add a condition, e.g.,
userId == 12345
Immediate Window
Execute code while debugging:- While paused at a breakpoint, open Debug → Windows → Immediate (or
Ctrl+Alt+I) - Type expressions and press Enter:
Watch Window
Monitor variables continuously:- Open Debug → Windows → Watch → Watch 1
- Add expressions to watch
- Values update as you step through code
Call Stack
Inspect the call stack:- Open Debug → Windows → Call Stack (or
Ctrl+Alt+C) - See the sequence of method calls that led to the current point
- Click on frames to navigate
Tracepoints
Log messages without stopping execution:- Right-click in the margin where you’d set a breakpoint
- Select Tracepoint
- Enter a message like:
Player HP: {player.CurrentHp} - Messages appear in the Output window
Logging
Use Dalamud’s logging system for runtime diagnostics:View Logs
Logs appear in:- Dalamud log -
/xllogin-game - Log file -
%AppData%\XIVLauncher\dalamud.log - Output window - In your IDE when debugging
Structured Logging
Use structured parameters:Exception Handling
Try-Catch Blocks
Always wrap risky operations:First-Chance Exceptions
Catch all exceptions in Visual Studio:- Debug → Windows → Exception Settings (or
Ctrl+Alt+E) - Check Common Language Runtime Exceptions
- Debugger will break on all exceptions, even caught ones
Exception Filter
Break only on specific exceptions:Common Issues
Breakpoints Not Hitting
Breakpoints Not Hitting
Causes:
- Plugin not loaded or outdated version
- Code not matching the compiled assembly
- Debugging symbols not loaded
- Verify plugin is loaded:
/xlplugins - Rebuild in Debug mode
- Ensure breakpoint is on an executable line
- Check Debug → Windows → Modules to see if your DLL is loaded
- Right-click the DLL → Load Symbols
Game Crashes When Debugging
Game Crashes When Debugging
Causes:
- Unhandled exception in plugin code
- Invalid memory access
- Deadlock or infinite loop
- Enable first-chance exceptions to catch the error
- Add try-catch blocks around suspicious code
- Check for null references
- Validate memory addresses before dereferencing
- Review recent changes to plugin code
Variables Show Optimized Away
Variables Show Optimized Away
Cause:
Building in Release mode with optimizations enabled.Solution:
Build in Debug mode:
Cannot Edit Code While Debugging
Cannot Edit Code While Debugging
Limitation:
Edit and Continue is not supported for plugins since they run in a separate AssemblyLoadContext.Workaround:
- Stop debugging
- Make changes
- Build
- Hot reload your plugin:
/xldev→ Reload Plugin - Re-attach debugger
Performance Issues While Debugging
Performance Issues While Debugging
Causes:
- Too many breakpoints
- Watching complex expressions
- First-chance exceptions enabled
- Remove unnecessary breakpoints
- Simplify watch expressions
- Disable first-chance exceptions
- Use tracepoints instead of breakpoints for logging
Hot Reload
Dev plugins support hot reloading without restarting the game:Reload in Game
- Type
/xldevin-game - Go to the Plugin Dev tab
- Find your plugin
- Click Reload
Memory Debugging
When working with memory and pointers:Memory Window
View raw memory:- Debug → Windows → Memory → Memory 1
- Enter an address expression
- View bytes, words, or other formats
Pointer Validation
Always validate pointers:Using SigScanner
Debug signature scanning:Performance Profiling
Stopwatch Timing
Measure execution time:Frame Time Monitoring
Monitor UI draw performance:Testing Strategies
Unit Testing
While full unit testing is challenging, you can test pure functions:Tests/UtilityTests.cs
Integration Testing
Test in-game with controlled scenarios:Debug Commands
Add debug commands for testing:Best Practices
Log Liberally
Add logging statements throughout your code. You can filter by log level later.
Validate Inputs
Always validate data from external sources (game memory, files, IPC) before using it.
Use Assertions
Use Debug.Assert for invariants that should never be false:
Test Edge Cases
Test your plugin with unusual conditions: level 1 character, empty inventory, etc.
Remote Debugging
For debugging on another machine:- Install Remote Debugging Tools on the game machine
- Start the remote debugger:
msvsmon.exe - In Visual Studio: Debug → Attach to Process
- Change Connection type to Remote (no authentication)
- Enter the remote machine name
- Select
ffxiv_dx11.exe
Next Steps
Troubleshooting
Common issues and solutions
Testing Guide
Learn about testing strategies
Game Integration
Work with game state and data
Advanced Topics
Explore hooking, memory, and signatures