Reading a freeze: watchdog thread dumps
A freeze is not lag, and the fix is different
Low TPS and a freeze look similar from a player's seat but they are different faults. Lag is the server doing slightly too much work every tick, for ever. A freeze is one tick that never finished. Treating a freeze as a lag problem is why people buy more RAM and stay frozen.
| Symptom | What it is | Where to go |
|---|---|---|
| Everything is sluggish but keeps moving, TPS reads 14–18 | Lag: too much work per tick | Fixing lag & low TPS |
| Total stop for 5–30 s, then everything catches up at once | Freeze: one tick blocked | This guide |
| Players are kicked with “Timed out” during the stop | A freeze long enough to pass the timeout | This guide |
| Server process vanishes and restarts itself | A crash or an out-of-memory kill | Memory & Java flags |
When a freeze ends, every queued action lands in one go: mobs teleport to where they should be, your hunger drops several points at once, chat arrives in a block. Real lag never does that, because it never stopped to queue anything.
Paper already recorded what happened
You do not need to reproduce a freeze to diagnose it. Paper runs a watchdog thread that watches the main thread, and when the main thread stops answering it writes a full stack trace of what that thread was doing. That trace names the exact plugin, class and line.
Open the Console tab, or logs/latest.log in the file manager, and search for:
has not responded
What you are looking for:
[20:17:00] [Paper Watchdog Thread/ERROR]: The server has not responded for 10 seconds! Creating thread dump [20:17:00] [Paper Watchdog Thread/ERROR]: Current Thread: Server thread [20:17:00] [Paper Watchdog Thread/ERROR]: Stack: org.bukkit.configuration.file.YamlConfiguration.loadConfiguration(YamlConfiguration.java:310) me.example.gencore.laboratory.LaboratoryManager.config(LaboratoryManager.java:1644) me.example.gencore.laboratory.LaboratoryManager.cropMasteryXpMultiplier(LaboratoryManager.java:220) me.example.gencore.farm.FarmManager.applyCropBreakXp(FarmManager.java:902) me.example.gencore.farm.listener.FarmListener.onFarmClick(FarmListener.java:312) io.papermc.paper.plugin.manager.PaperEventManager.callEvent(PaperEventManager.java:54)
The bottom of the stack is Paper calling an event. The top is whatever was running when
time ran out. The line that matters is the highest one belonging to a plugin rather than
to org.bukkit, net.minecraft or io.papermc. In this dump it is here
LaboratoryManager.config at line 1644. That is your culprit, named for you.
If the log has rotated, older freezes are still in logs/ as
.log.gz files. Download one and open it. The dumps are in there too.
Read the stack like a sentence
Each line is “this method called the one above it”. You care about three things, and you can usually get all three from one dump.
Which plugin
The package name. me.example.gencore.… is a plugin called GenCore;
com.sk89q.worldedit.… is WorldEdit. Cross-check against
/plugins in game if the name is not obvious.
What it was doing
The top few frames tell you the kind of work, and that points straight at the fix:
| Top of the stack mentions | It was doing | Usual cause |
|---|---|---|
YamlConfiguration.loadConfiguration, FileInputStream | Reading a file from disk | A config re-read per event instead of cached once |
java.sql., SQLiteConnection, executeQuery | A database query | A query on the main thread instead of async |
SocketInputStream.read, HttpClient | Waiting on the network | An API or webhook call not run async |
getChunkAt, ChunkHolder, PaperChunk | Loading world chunks | A plugin walking blocks across chunk borders |
Object.wait, park, ReentrantLock | Waiting for another thread | A deadlock: see step 5 |
What triggered it
The bottom plugin frame is usually a listener, and its name tells you the player action.
onFarmClick means someone broke a crop. That is your reproduction step, and it is
why freezes so often arrive in bursts: one player repeating one action.
Confirm it, do not guess
One dump is a snapshot. Before you blame a plugin, check that the pattern repeats and that the server is otherwise healthy.
Do the dumps agree?
Count them, then compare. Several freezes with the same top frame is as close to proof as you get:
has not responded Current Thread
Is it idle-healthy?
Check the Console graphs with nobody online. A server that sits at 2–3% CPU and freezes only when someone plays has a code problem, not a capacity problem. If it is pinned at 100% with an empty world, that is a different fault.
A tick is 50 ms. If a plugin does something costing 3–4 ms and the stack shows it being called a dozen times per event, that is a blown tick for a single action, and a few hundred actions is your ten-second freeze. If the numbers do not reach 50 ms, keep looking.
Cross-check with spark
Install spark, run a profile while the problem happens, and open the link it prints. If the same plugin method sits at the top of the profile too, you are done. Keep the profile. It is the single most useful thing to attach to a bug report.
spark profiler start --timeout 120 spark profiler stop
Three stacks worth recognising
Blocking I/O on the main thread
File reads, database queries and HTTP calls in a stack under an event listener. The server is not busy, it is waiting. This is the most common freeze and almost always a plugin bug: the work should be cached or run async. There is usually no setting that fixes it.
A deadlock
Top frames are Object.wait, LockSupport.park or a lock class, and the
freeze never ends. The watchdog keeps firing until the server is killed. Note every plugin
named across all the dumps and report it; nothing you can configure will clear it.
Garbage collection
Frames mentioning GC, or log lines about a long pause with no plugin in the stack at
all. This one is a tuning problem rather than a plugin bug. See
Memory & Java flags.
If the stack shows one thread waiting on a file or a query, the heap size and the core count are irrelevant. The server is not short of anything, it is stopped. Upgrading is the most common wasted spend on this fault.
Narrow it down when the stack is unclear
Dumps that name only Paper classes, or a different plugin each time, need bisection instead.
Disable, do not delete
Rename the jar to plugin.jar.disabled rather than removing it, so you can put it back
and so its config survives. Restart fully. A reload leaves the old classes loaded and will
waste your afternoon.
Halve the list each time
Disable half your non-essential plugins, play until you would expect a freeze, then halve again. Twenty plugins is about five restarts. Guessing one at a time can take twenty.
Check for an update first
Before any of that, compare each suspect's version against its download page. Freezes are frequently a known bug fixed two releases ago, and reading one changelog beats five restarts.
Reporting it so it actually gets fixed
If the fault is in a plugin's code, the fix belongs to its developer, and a report with a stack trace in it tends to get answered quickly, because you have done the hard part. Include:
| Include | Why it helps |
|---|---|
| The full watchdog dump, not a screenshot of part of it | The frames you trimmed are often the ones that identify the path |
| Paper version and build, and your Java version | /version gives both; bugs are usually version-specific |
| The plugin version, exactly | “Latest” means nothing a month from now |
| What the player was doing | Your reproduction step, from the listener name |
| A spark profile link | Shows cost over time, not one instant |
| How often, and whether it is idle-healthy | Separates a code bug from a capacity problem |
If a freeze starts the day a plugin updates, the quickest fix is the previous version. Keep the old jar when you update a plugin you depend on. Rolling back takes a minute, waiting for a fix can take weeks.
Troubleshooting
The log has no “has not responded” lines at all
Then the main thread never stopped for long enough, and what you have is lag rather than
a freeze. Start with Fixing lag & low TPS.
If the server vanished and came back instead, look for Exception or
OutOfMemoryError near the end of the previous log, and read
Memory & Java flags.
The stack only shows Minecraft classes, no plugin anywhere
Usually chunk or world I/O: look for getChunkAt or
ChunkHolder. Common triggers are a world border set enormously large, a
pre-generation task, or a plugin scanning a big region on a timer rather than from a
listener, which is why it never appears in the dump. Check your scheduled tasks and any
pre-generator before bisecting.
It only freezes on restart or when saving
A pause while the world saves is normal and scales with world size; Paper does most of it incrementally. If it lasts long enough to kick players, check whether something forces a full save on a timer, and look at how large your world has grown. See Backups & restoring.
I found the plugin but there is no setting to turn the feature off
That happens, and it means the fix has to come from the developer. Report it with the dump. Meanwhile your options are the previous version of the jar, disabling the plugin, or living with it. If the plugin is closed-source, do not patch the jar on a live server: the next update silently overwrites it.