Guides · Engineering
Error tracking for Minecraft plugins: find the bug before the 1-star review
How Spigot and Paper plugin exceptions reach the console, why waiting for reports fails, and how to collect, group and fix errors from every server.
For every server owner who reports a bug, many more just see a red stack trace in their console, sigh, and uninstall your plugin. Some leave a one-star review on the way out. The bug that hurts you most is the one nobody tells you about.
This guide covers where plugin errors end up, why waiting for reports isn't enough, and how to see every error from every server.
Where your plugin's exceptions go
When your code throws on a server, the server catches it and logs it, so the server keeps running. Each kind of entry point has its own message in the console:
| Where it happened | What the console says |
|---|---|
| An event handler | Could not pass event PlayerJoinEvent to YourPlugin v1.2.0 |
| A command | Unhandled exception executing command 'arena' in plugin YourPlugin v1.2.0 |
| A scheduled task | Plugin YourPlugin v1.2.0 generated an exception while executing task 1234 |
| Startup | Error occurred while enabling YourPlugin v1.2.0 (Is it up to date?) |
Followed by the stack trace. The server owner sees it, maybe. You don't, unless they copy it and send it to you.
Why "send me your logs" doesn't scale
Asking for logs works when you have ten users. With a thousand servers it breaks down:
- Most owners never report. Reporting takes effort; uninstalling takes one click.
- Reports arrive late and incomplete. "It doesn't work" with no version, no server software and a screenshot of half a stack trace.
- You can't tell how big a bug is. One report could be one server or three hundred.
- You can't tell if your fix worked. No news after an update could mean fixed, or could mean people gave up.
What good error tracking does
Whatever tool you use, or if you build it yourself, these are the parts that matter:
- Catch errors where they happen. Exceptions that go through your plugin's code, from event handlers, commands, tasks and async threads, plus the ones you catch yourself and want to know about.
- Group them. The same bug on 500 servers should be one issue with a count, not 500 alerts. Grouping by the exception type and the top frames of your code (without line numbers, so a small edit doesn't split an issue) works well.
- Keep the context. Plugin version, server software, Minecraft version, Java version. Most plugin bugs only happen on some combination of these.
- Strip personal data. Stack trace messages often contain player names, UUIDs and IP addresses ("Could not find player Notch at 1.2.3.4"). Replace them before anything leaves the server.
- Track regressions. When you mark an issue fixed and it happens again in a newer version, you want to know straight away.
- Never hurt the server. Capture off the main thread, cap how much is sent, and never throw from the error reporter itself.
Report the errors you catch
The server only logs exceptions that escape your code. The ones you catch and swallow are invisible:
try {
database.save(arena);
} catch (SQLException e) {
getLogger().warning("Couldn't save arena: " + e.getMessage()); // the stack trace is gone
}
If an error matters enough to log, it usually matters enough to report with its stack trace. Pass the exception to your logger (getLogger().log(Level.WARNING, "Couldn't save arena", e)) or to your error tracker directly.
Options
- Ask for logs (mclo.gs, pastebin, Discord). Free, works for small plugins, misses most errors.
- A general error tracker like Sentry, shaded into your plugin. Powerful, but it's built for web apps: you'll need to scrub player data yourself, map Bukkit's thread model, and watch the event quota of the free plan when one bug fires on thousands of servers.
- A tool built for plugins. PluginAnalytics captures every exception that goes through your plugin on any server with no extra code, groups it into issues, replaces player names, IPs and UUIDs, shows the versions where it was first and last seen, and notifies you of new errors and regressions. It also collects your plugin's own log lines from every server, and for obfuscated plugins it turns stack traces back into your real class names.
Fix the right bug first
Once errors arrive on their own, prioritise by impact, not by how loud the report was:
- How many servers hit it, not how many times. One server in a loop can log a million errors.
- Which versions. A bug only on an old version is fixed by asking people to update. A bug that appeared in your latest release is urgent.
- Where in the flow. An error on startup costs you the install. An error in a rarely used command can wait.
Then ship the fix, mark the issue resolved, and watch: if it comes back in the new version, you'll know before the next review does.
More guides
Which part of your Minecraft plugin causes lag (and how to fix it)
Find the part of your Spigot or Paper plugin that causes lag: MSPT, spark profiles, the usual suspects and how to see its cost across all servers.
4 min readEngineeringObfuscating a Minecraft plugin with ProGuard and Gradle (without breaking stack traces)
A working ProGuard setup for Spigot and Paper plugins with Gradle: the task, the keep rules Bukkit needs, and readable stack traces with mappings.
3 min read