Why Your Minecraft Server Keeps Crashing (and How to Find the Cause)
Find out why your Minecraft server keeps crashing — read the crash report and logs/latest.log, then check memory, the watchdog, plugins, chunks, and Java.
A server that keeps crashing is almost always telling you exactly why, in a file you haven't opened yet. When the process actually dies, the server writes a timestamped report into crash-reports/; while it's still running, every error and warning streams into logs/latest.log; and a fault below Java drops an hs_err_pid<pid>.log in the working folder. The cause is nearly always one of five things, and they fall in a rough order to work through: the heap ran out of memory, the watchdog killed a frozen tick, a plugin misbehaved, a region file is corrupt, or the wrong Java version is installed. Read the report first, then work down the list. If what you're actually chasing is stutter rather than a full crash, server TPS and lag spikes is the companion to keep open, because lag is what usually precedes the crash.
Crash or lag? Read the right file first
These two get mixed up constantly, and they send you to different files. A crash is the process dying and leaving a report behind. Lag is the server falling behind on ticks while it keeps running. The server aims for 20 ticks per second, one tick every 0.05 seconds, and when it can't keep that pace you get Can't keep up! Is the server overloaded? Running 2123ms or 42 ticks behind in the log. Older builds phrase it as Did the system time change, or is the server overloaded? Running 2000ms behind, skipping 40 tick(s) — same meaning, the numbers are always dynamic.
The one that looks scariest but isn't a crash is the watchdog early-warning dump, headed --- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---. That fires when a tick has been running for ten-plus seconds, and Paper is being literal: it's a severe-lag warning, not a bug. It often comes right before a real crash, so treat it as a head start rather than the event itself.
So before anything else: did the process actually die and write a file to crash-reports/, or is it still up and complaining? If it's still up, you're diagnosing lag, and you can do that live (see the last section) instead of reading a crash report that doesn't exist yet.
Out of memory: the heap is too small for the load
The most common true crash is java.lang.OutOfMemoryError: Java heap space (you'll sometimes see GC overhead limit exceeded instead — same root). The live heap outgrew the -Xmx maximum you gave the JVM, usually because too many chunks are loaded, entities and dropped items have piled up, or a plugin is leaking memory. The fix is to give it more room: raise -Xmx, and set -Xms equal to it. Paper's reasoning is blunt — if -Xms is lower than -Xmx you have unused memory, and unused memory is wasted memory. The garbage collector runs better the more heap it's handed, and Aikar's guidance is at least 6-10GB no matter how few players you have.
Two traps here. First, don't hand the whole machine to the heap. Leave the JVM and the OS about 1000-1500MB of headroom, or the operating system's out-of-memory killer steps in and the process simply vanishes with Killed and no Java stack trace at all — which is maddening to diagnose if you're only looking in crash-reports/. Second, high RAM usage is not a leak. It's normal for the Java process to use the RAM it's given; a real leak is the heap climbing to the ceiling under ordinary load until it throws. If you're tuning the launch line, the best Aikar JVM flags writeup has the full string, and reducing RAM usage covers trimming the load itself so you don't just mask it.
The watchdog killed a frozen tick
If the log ends with A single server tick took 60.00 seconds (should be max 0.05) followed by Considering it to be crashed, server will forcibly shutdown., that's the watchdog, and it's working as designed. One tick hung past the timeout, so Paper deliberately crashed the server to keep a half-finished tick from corrupting the world. You'll see it as java.lang.Error: ServerHangWatchdog detected... in the stack trace.
The watchdog didn't cause the freeze — it reacted to it. Something inside that tick blocked: an infinite loop, a synchronous database or web call on the main thread, a runaway scheduled task, or mass entity and chunk processing all landing at once. The fix is finding what froze, which the thread dump under the crash usually names.
The timeout lives in spigot.yml as settings.timeout-time (default 60, in seconds), with settings.restart-on-crash (default true) running settings.restart-script (default ./start.sh) afterward. Resist the urge to set timeout-time to something huge or zero. That only mutes the alarm and trades a clean crash for a real chance of a corrupted world — the freeze is still there.
A misbehaving or outdated plugin
This is the single most common owner-side cause, and the report points right at it. Paper's rule is that in most cases the plugin whose name appears on the stack trace is the one causing the problem. Open latest.log or the watchdog thread dump and read from the top: the first package name that isn't Paper's or Minecraft's is the plugin at fault. Update it to a build that matches your server version, or pull it out to confirm the crashes stop.
Plugin crashes spike right after a server update, because a plugin compiled for the old version gets loaded on the new one. That's acute right now: 26.1 is the stable target most plugins are built against, while Paper's 26.2 builds are still experimental and flagged unsupported, so plugins routinely lag the server. If you're running a plugin-heavy setup, staying on the stable 26.1 builds until your plugins catch up saves you this whole category of crash. A short, current plugin list is in must-have Paper plugins for a new server.
Corrupt chunks and the wrong Java
The last two are rarer but distinctive. A corrupt region file — something like world/region/r.X.Z.mca — crashes the server every time that area loads or ticks, often reproducibly at the same coordinates or whenever one specific player logs in. The stack trace points at chunk, region, or NBT loading. Restore that region or the world from a backup, or delete the single corrupt region so it regenerates from scratch.
A Java version mismatch isn't a runtime crash at all — the server never starts. The jar was compiled for a newer JDK than you've installed, so the JVM refuses it with java.lang.UnsupportedClassVersionError and a line like has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to 61.0. Class file 65.0 is Java 21, which current builds want. Install the right JDK and confirm with java -version. Separately, a report headed A crash happened outside the Java Virtual Machine is a native fault — bad RAM, a broken JDK, a native library — recorded in hs_err_pid<pid>.log rather than a normal crash report, and it points at the box, not your config.
Catch the lag before it crashes
If the watchdog keeps firing, profile the freeze before it becomes a crash. Paper bundles Spark: run /tps to read your ticks-per-second, then /spark profiler start --timeout 300 for a five-minute capture, or /spark profiler start --only-ticks-over 100 to record only the spikes that lead to a watchdog kill. The profiler attributes tick time to the exact plugin or task eating it. When the stack points at world ticking rather than a plugin, the usual offenders are dense entity and item buildup from big mob farms, fast liquid updates, long hopper chains, and new chunks generating on the fly.
FAQ
My server shows "Killed" with no crash report — where did it go?
That's the operating system's out-of-memory killer, not Java. When the machine itself runs out of memory, the OS terminates the process before Java can throw OutOfMemoryError or write to crash-reports/, so you get a bare Killed and nothing else. On Linux you can confirm it in the kernel log — dmesg or journalctl -k shows an Out of memory: Killed process line naming the java PID. The fix is to lower -Xmx so the heap plus JVM overhead fits under the machine's total RAM with 1000-1500MB to spare, or move to a host with more memory; counterintuitively, handing less to the heap is often what stops these.
How do I tell a corrupt chunk from a plugin crash when both hit on login?
Both can crash the instant a player joins, but the stack trace separates them. A corrupt region names chunk, region, or NBT loading and reproduces at the same coordinates regardless of which build you run; a plugin crash names a plugin package at the top and follows that plugin across world locations. The quick test: remove the suspect plugin and see if the same player can log in. If they still crash with the plugin gone, restore that region from backup or delete the r.X.Z.mca so it regenerates.
There's no crash-reports file at all — where else should I look?
A file lands in crash-reports/ only when Java itself writes one, and it sits in the server's working directory next to the jar — named like crash-yyyy-mm-dd_hh.mm.ss-server.txt, not in the client's %appdata%\.minecraft folder. If that file is missing, the failure happened below Java: look for hs_err_pid<pid>.log in the same folder for a native fault, or a bare Killed in the console for the OS out-of-memory killer. A watchdog kill, by contrast, does write a normal report and ends with Considering it to be crashed, server will forcibly shutdown.
The crash log barely changed after I updated the server — what now?
If crashes started or got worse right after an update, the split is startup versus in-play. If the server never reaches its Done! startup line and the console shows java.lang.UnsupportedClassVersionError, your JDK is older than the jar needs — install Java 21 and recheck with java -version. If it boots fine but crashes once people are playing, a plugin compiled for the previous version is the likely cause; match each plugin to a build for your current version, or roll the server back to the stable 26.1 line until the plugins you depend on have caught up.


