How to Read Minecraft Server Logs: Errors and Stack Traces

Reading Minecraft server logs, errors and stack traces

Every Minecraft server problem eventually becomes a reading problem. The server already told you what broke, in plain text, usually within two seconds of it happening. The trouble is that the answer is buried in four hundred lines of INFO chatter, wrapped in a Java stack trace, and phrased in a dialect that only looks readable once someone shows you the map. This guide is that map. It exists to help you stop guessing, stop restarting blindly, and stop pasting screenshots into Discord hoping a stranger decodes them.

It is written for server owners who administer their own Linux box, for staff who get handed a console tab and told “it crashed”, and for plugin developers who would rather read a log than ask for one. You do not need to know Java to use this. You need to know where to look, what order to read things in, and which lines are the cause rather than the echo.

Everything below was reproduced on purpose. We ran a Paper 26.2 test server (build 129) on Ubuntu 26.04 with Java 25.0.4.1, broke it in seven specific ways, and kept the exact wording of each failure so you can compare it against your own console. That matters, because log wording drifts between versions and between forks, and a tutorial that invents example errors teaches you to look for text that will never appear on your screen.

The Log Level Ladder, Decoded

Minecraft servers log through Log4j 2, which is configured by the log4j2.xml file inside your server jar. The level on each line is a severity tag, not a verdict. Reading it correctly is the first half of triage: it tells you whether you are looking at context, a warning that was handled, or a genuine failure. The Apache Log4j documentation defines the ladder formally; here is what it means on a Minecraft server in practice.

LevelWhat it usually means hereDo you act?
TRACEExtremely granular internals, almost never enabled by default. Packet-level or per-tick detail.No. Noise unless you are debugging a specific subsystem.
DEBUGDeveloper detail: chunk load decisions, config resolution, cache misses. Enabled per plugin.Only when reproducing a bug on request.
INFONormal operation: world loaded, player joined, plugin enabled, backup finished.No. This is your timeline anchor.
WARNSomething unexpected that the server worked around. Fallbacks, deprecated calls, ignored config keys.Often. Not fatal, but it is technical debt.
ERRORA task failed. A plugin may disable itself, a command may error, an event may drop.Yes, but read the whole line: the server is usually still running.
FATALThe process cannot continue. Startup aborts or the JVM exits.Immediately. Nothing else matters until this is fixed.

The single most expensive misconception in Minecraft administration is that ERROR means the server is down. It does not. A plugin can throw an ERROR, disable itself, and leave the world running perfectly for the other nineteen plugins. You will see the pairing constantly: an error line, then Disabling PluginName, then business as usual. The server is up. One feature is gone. That is a very different incident from a crash, and it needs a very different response.

  • WARN is not a synonym for broken. A warning that says the server is falling back to a default is information about a config you should fix later.
  • ERROR is scoped. Ask “what failed”, not “is it dead”.
  • FATAL is the only level that reliably means stop-the-world. Even then, read upward: the cause sits above the fatal line, not below it.
  • Absence of errors is not health. A server can sit at 8 TPS with a perfectly clean log.

Where Minecraft Keeps Its Logs

Before you can read a log you have to find it. On a Linux server there are five places worth knowing, and they answer different questions.

  • logs/latest.log is the live file for the current run. It is rewritten every time the server starts, which is exactly why you should copy it somewhere before restarting. This is the file you tail while the server is running.
  • logs/2026-10-19-3.log.gz and its siblings are the rotated archives. The number is the run index for that day. These are gzipped, so plain grep will not read them; you need zgrep or zcat. If you restarted to “fix” something, the evidence is here, not in latest.log.
  • The console is the same stream you see in the terminal or panel, but truncated by scrollback. Never trust it as a record. If it scrolled, it is gone.
  • journalctl captures stdout and stderr when the server runs under systemd, along with the exit code and the OOM killer’s opinion. This is the only place that survives the JVM dying mid-write, and its filtering is far better than grepping a 200 MB file. See the journalctl manual for the full filter syntax.
  • crash-reports/ and hs_err_pid*.log appear when the JVM itself dies. A crash report is a formatted summary with the description, the stack, and the loaded plugin list. An hs_err_pid file is a HotSpot fatal error dump: it names the failing frame, the memory map, and the JVM flags. Both are gold when the server vanished without a graceful shutdown line.

Where that output lands is partly a server setting. The vanilla and Paper server.properties options and the Paper configuration reference cover the knobs, but logging behavior itself comes from the bundled Log4j config, and Paper’s official documentation is the place to check before editing it.

Anatomy of a Stack Trace

A stack trace is a receipt for a failure. It has five parts, and once you can name them you can read any of them in about fifteen seconds.

[12:04:31 ERROR]: [Chunky] Failed to load configuration
org.bukkit.configuration.InvalidConfigurationException: while parsing a flow sequence
    at org.bukkit.configuration.file.YamlConfiguration.loadFromString(YamlConfiguration.java:60) ~[paper-api.jar:?]
    at com.popcorn.chunky.ChunkyConfig.load(ChunkyConfig.java:47) ~[Chunky-1.4.36.jar:?]
Caused by: while parsing a flow sequence
    at org.yaml.snakeyaml.composer.Composer.composeNode(Composer.java:171) ~[snakeyaml.jar:?]
  • The exception line is the full class name and the message: InvalidConfigurationException: while parsing a flow sequence. This is what you search for. It is stable across servers and worth quoting verbatim.
  • The at frames are the call stack, newest call on top. Each frame is class, method, file, and line number. The square-bracket suffix names the jar and version, which is how you learn a failing method lives in Chunky 1.4.36 and not in Paper.
  • Caused by is the real exception, wrapped by a friendlier one. The last Caused by in the chain is almost always the actual fault. Read these before you read a single frame.
  • Suppressed appears when cleanup code also fails. It is context, not cause. Ignore it on the first pass.
  • Line numbers point at the source file of the jar that threw. If the line number is inside a plugin’s own class, the bug is that plugin’s config or code, not the server core.

Top-down versus bottom-up

Read top-down when you want to know what the server was doing: the top frames are the trigger, often an event handler or a scheduled task. Read bottom-up when you want to know why it failed: the bottom of the Caused by chain is the primitive fault. For plugin crashes, the practical habit is to jump to the lowest Caused by, read its message, then walk back up to the first frame that mentions a plugin jar. That pair of lines is your whole diagnosis most days.

Seven Real Errors, Reproduced on a Test Server

These are deliberately triggered failures with the wording left intact. Compare them against your own console before you search the internet; the exact phrasing is what makes a search work.

1. Broken plugin YAML

org.bukkit.configuration.InvalidConfigurationException: while parsing a flow sequence
 in 'reader', line 12, column 5:
      - [unclosed
expected ',' or ']', but got <stream end>
Caused by: while parsing a flow sequence

One missing closing bracket in a Chunky config produced this. Notice what the message gives you: a file position, line 12, column 5, and a plain-English expectation. The stack is not the story here; the coordinates are. Open the file at that line, fix the bracket, done. Chasing the SnakeYAML frames is wasted effort because the parser is behaving correctly.

2. Missing plugin dependency

[ChestShop] No Economy adapter found! You need to install either Vault or Reserve!
[ChestShop] Disabling ChestShop v3.13-pre-1 (build 474)

Two lines, no stack trace, complete diagnosis. The plugin names its missing dependency, then disables itself. Note the version string, because “ChestShop 3.13-pre-1” is what you will need in a bug report. This is the classic shape of a soft failure: the server is fine, players can still build, but every shop command now fails. If a player reports “shops are broken” and nothing is crashing, this is what you go looking for.

3. Port already in use

**** FAILED TO BIND TO PORT!
The exception was: io.netty.channel.unix.Errors$NativeIoException: bind(..) failed with error(-98): Address already in use
java.lang.IllegalStateException: Failed to bind to port

Starting a second server from a clean directory on port 25565 gave this. The tell is the native errno, error(-98), and the phrase Address already in use. There is nothing wrong with your world, your plugins, or your Java version; something else owns the port. Find it with ss -ltnp, look at the PID column, then decide whether that process is a zombie server you forgot about or a service you should stop properly.

4. Out of memory before the world loads

java.lang.reflect.InvocationTargetException
Caused by: java.lang.OutOfMemoryError: Java heap space

With -Xmx96M, startup died inside Paperclip before any world was touched. That is the lesson: OOM can happen during class loading and library scanning, long before chunks exist. If your startup log ends abruptly with an invocation wrapper, do not assume the plugin list is at fault. Check the Caused by line, then check your start script’s memory flags. The wrapping exception exists only because reflection rethrows checked exceptions, so ignore the wrapper entirely.

5. Watchdog after a 65-second stall

The server has stopped responding! This is (probably) not a Paper bug.
Server thread dump (Look for plugins here before reporting to Paper!):
Current Thread: Server thread
... hundreds of lines ...
Stopping server

We froze the JVM with SIGSTOP for 65 seconds. The watchdog fired, dumped every thread, and killed the server. Read this as evidence, not as blame. The watchdog detected a stall; it did not cause one. Start at the top of the Server thread dump and look for a frame belonging to a plugin jar, because that is where the main thread was when time stopped. Everything below it is the rest of the server idling, and the length of the dump is normal.

6. Datapack metadata warning

Error reading pack metadata, attempting fallback type
com.google.gson.JsonParseException: Pack declares support for version newer than 81, but is missing mandatory fields min_format and max_format

An older datapack loaded anyway, thanks to the fallback. The word “fallback” is your signal that the server is continuing. Fix it because version drift compounds, but do not panic-restart at 2 AM over a WARN.

7. Log spam has a measurable cost

We wiped 2,000 villagers in one event. The server wrote 2,002 lines and 498,607 bytes of Villager was killed, averaging about 249 bytes per line. That is half a megabyte from one command, on one quiet test server. Scale that to a farm running in the background of a 60-player server and you get a log that rotates every hour, destroys your history, and buries the actual error you will need tomorrow. The fix is at the source: reduce the noisy event, raise that logger’s threshold, or filter it out of your daily reading. Either way, spam is not free.

The Seven-Step Triage Workflow

This order is intentional. Each step narrows the search space, and doing them out of order is what produces twenty-minute guesswork sessions over a thirty-second fix.

  1. Note the timestamp and reproduce. Write down the exact time a player reported the problem, then try to trigger it yourself. A timestamp turns a 200,000-line log into a 300-line window.
  2. Find the first ERROR or WARN, not the last line. The bottom of a log is whatever happened to be printing when you looked. The first anomaly is the seed; everything after it is fallout.
  3. Read the exception message and the whole Caused by chain. Skip the frames until this step. Messages are written for humans; frames are written for debuggers.
  4. Identify the thread. Server thread means the main tick loop. A named plugin thread or a ForkJoinPool or pool-N-thread worker means async work. This tells you whether the symptom is a lag spike or a background failure.
  5. Map the top plugin frame to a plugin and version. The jar name in brackets plus the class package usually answers “whose bug is this” without any searching.
  6. Check the config line or dependency name. If the message contains a line and column, open that file. If it names another plugin, confirm it is installed and enabled.
  7. Fix one thing, restart, verify. One change per restart. If you change three things and the error vanishes, you have learned nothing and will meet it again.

Command Cheat Sheet for Linux Servers

These are the commands worth memorizing. Run them from your server directory.

# Watch the live log
tail -f logs/latest.log

# Every error and exception, with line numbers
grep -n -i -E "error|exception" logs/latest.log

# Context around a specific failure
grep -n -B 5 -A 20 "OutOfMemoryError" logs/latest.log

# Search rotated archives
zgrep -i "Failed to bind to port" logs/*.log.gz

# systemd-managed servers
journalctl -u minecraft -f
journalctl -u minecraft --since "2026-10-19 12:00" --until "2026-10-19 12:30"
journalctl -u minecraft -p err -b

# Who owns the port?
ss -ltnp | grep 25565

# Disk and memory pressure
df -h; du -sh logs/
free -h
ps aux --sort=-%cpu | head -n 15
  • tail -f plus a second terminal is the fastest way to correlate a player action with a log line.
  • grep -n gives you line numbers so you can reopen the file at the right offset in an editor.
  • journalctl -p err -b shows only error priority from the current boot, often the cleanest view of a crash you missed.
  • zgrep is mandatory for archives; plain grep on a .gz file silently returns nothing, which has convinced many admins a log was empty.
  • ss -ltnp needs root to show the owning process; without it you see the socket but not the PID.
  • df -h and du -sh logs/ catch the forgotten failure mode where logging filled the disk and the JVM died on write.

Error Text to Cause: Quick Reference

Log textLikely causeFirst check
Address already in use / error(-98)Another process owns the portss -ltnp
OutOfMemoryError: Java heap spaceHeap exhausted, or -Xmx too lowStart flags, then free -h
UnsupportedClassVersionErrorJava too old for the jarjava -version
No Economy adapter foundMissing Vault or economy providerPlugin list and load order
while parsing a flow sequenceMalformed YAML in a plugin configLine and column in the message
has stopped responding! plus thread dumpMain thread stalled past the watchdog limitTop plugin frame in the dump
Error reading pack metadataDatapack format driftpack.mcmeta format fields
Failed to load eula.txtEULA not acceptedeula=true in eula.txt
Unknown or incomplete commandTypo, or the plugin owning it is disabledPlugin enabled state

Reporting a Crash the Right Way

When a stack trace genuinely belongs to Paper or a plugin author, your report decides whether you get help. Screenshots get ignored because nobody can search or copy text from them. Paste the full log to a paste service, not a 4,000-character Discord message that truncates the middle, and never post the same log in three channels at once.

  • Full log from startup to the failure, uploaded to a paste site and linked. The startup block contains every version they need.
  • Exact versions: server jar and build, Java, the failing plugin and its build number.
  • Reproduction steps in numbered order, including what you expected to happen.
  • What you already tried, so nobody repeats your work.
  • No secrets: strip tokens, database passwords, IP addresses, and player identifiers before pasting. Config files often carry all four.

Raw Logs vs Panels and spark: Pros and Cons

Panels, log viewers, and profilers are excellent additions. They are not replacements, and knowing when each wins saves time.

  • Raw logs, pros: nothing is filtered out; every line is attributable and searchable; archives survive for weeks; you can script them. Cons: no aggregation, no charts, and a wall of text that hides the signal in the noise.
  • Panels and viewers, pros: instant access, search highlighting, color by level, readable on a phone. Cons: scrollback limits, dropped lines during a crash, and no access to rotated archives. If the panel lost the line, the panel cannot help.
  • spark and profilers, pros: they answer “what is eating the tick” in a way no log can, and the output is shareable as a link. Cons: they diagnose performance, not exceptions. A clean profiler run tells you nothing about a missing dependency.
  • The practical split: logs for correctness and crashes, spark for performance, the panel for convenience. Read the raw file when the answer actually matters.

Common Mistakes and How to Avoid Them

  • Grepping only the last line. The last line is a symptom of the shutdown, not the cause. Search for the first ERROR or WARN and read forward from there.
  • Ignoring the first Caused by. The outermost exception is usually a friendly wrapper. The bottom of the chain is the truth.
  • Pasting an entire log into Discord. It gets truncated at the exact point where the useful frames were. Use a paste service and a link.
  • Assuming every WARN is fatal. A fallback warning is the server telling you it recovered. Silence it with a config fix, not a rollback.
  • Deleting or rotating logs before reading them. Copy latest.log to a dated file before every restart. This one habit prevents most “the log is gone” emergencies.
  • Restarting before reading. A restart overwrites the file that contains your answer.
  • Changing three things at once. You lose the ability to attribute the fix, which means the problem returns as a mystery.

If noisy plugins are a recurring theme in your logs, the same discipline applies to your plugin folder: fewer moving parts mean fewer failure modes. Our guide on how to audit and trim plugins to reduce server lag walks through that audit, and the 2026 server JAR benchmark is worth reading before you blame your jar for a stack trace that came from a plugin. Keep a tested backup routine so you can experiment with config fixes without fear, and if database warnings show up, see MariaDB tuning for LuckPerms and CoreProtect.

Frequently Asked Questions

<!– wp:yoast/faq-block {"questions":[{"id":"faq-question-1","question":"Where are Minecraft server logs stored?","answer":"In the logs folder of your server directory. latest.log is the current run; older runs are saved as dated .gz archives such as 2026-10-19-3.log.gz and must be read with zgrep or zcat. Servers run under systemd also log to journalctl -u <service>.","images":[],"jsonQuestion":"Where are Minecraft server logs stored?","jsonAnswer":"In the logs folder of your server directory. latest.log is the current run; older runs are saved as dated .gz archives such as 2026-10-19-3.log.gz and must be read with zgrep or zcat. Servers run under systemd also log to journalctl -u .”},{“id”:”faq-question-2″,”question”:”Does an ERROR in the log mean my server crashed?”,”answer”:”No. ERROR usually means one task or plugin failed. If the next line says the plugin is disabling itself, the server is still running and only that feature is gone. Only FATAL, a crash report, or a missing shutdown line point to a full crash.”,”images”:[],”jsonQuestion”:”Does an ERROR in the log mean my server crashed?”,”jsonAnswer”:”No. ERROR usually means one task or plugin failed. If the next line says the plugin is disabling itself, the server is still running and only that feature is gone. Only FATAL, a crash report, or a missing shutdown line point to a full crash.”},{“id”:”faq-question-3″,”question”:”How do I read a Java stack trace in a Minecraft log?”,”answer”:”Start with the exception message on the first line, then read the last Caused by in the chain, which holds the real fault. After that, find the first at frame that names a plugin jar. The jar name and version tell you whose code failed; the line number tells you where.”,”images”:[],”jsonQuestion”:”How do I read a Java stack trace in a Minecraft log?”,”jsonAnswer”:”Start with the exception message on the first line, then read the last Caused by in the chain, which holds the real fault. After that, find the first at frame that names a plugin jar. The jar name and version tell you whose code failed; the line number tells you where.”},{“id”:”faq-question-4″,”question”:”How do I fix Address already in use when starting a server?”,”answer”:”Another process already holds the port. Run ss -ltnp | grep 25565 to find the PID, then either stop that process or change server-port in server.properties. The error(-98) line in the log is the native confirm of a port conflict, not a Java or plugin problem.”,”images”:[],”jsonQuestion”:”How do I fix Address already in use when starting a server?”,”jsonAnswer”:”Another process already holds the port. Run ss -ltnp | grep 25565 to find the PID, then either stop that process or change server-port in server.properties. The error(-98) line in the log is the native confirm of a port conflict, not a Java or plugin problem.”}]} –>
Where are Minecraft server logs stored?

In the logs folder of your server directory. latest.log is the current run; older runs are saved as dated .gz archives such as 2026-10-19-3.log.gz and must be read with zgrep or zcat. Servers run under systemd also log to journalctl -u <service>.

Does an ERROR in the log mean my server crashed?

No. ERROR usually means one task or plugin failed. If the next line says the plugin is disabling itself, the server is still running and only that feature is gone. Only FATAL, a crash report, or a missing shutdown line point to a full crash.

How do I read a Java stack trace in a Minecraft log?

Start with the exception message on the first line, then read the last Caused by in the chain, which holds the real fault. After that, find the first at frame that names a plugin jar. The jar name and version tell you whose code failed; the line number tells you where.

How do I fix Address already in use when starting a server?

Another process already holds the port. Run ss -ltnp | grep 25565 to find the PID, then either stop that process or change server-port in server.properties. The error(-98) line in the log is the native confirm of a port conflict, not a Java or plugin problem.

{ “@context”: “https://schema.org”, “@type”: “FAQPage”, “mainEntity”: [ { “@type”: “Question”, “name”: “Where are Minecraft server logs stored?”, “acceptedAnswer”: { “@type”: “Answer”, “text”: “In the logs folder of your server directory. latest.log is the current run; older runs are saved as dated .gz archives such as 2026-10-19-3.log.gz and must be read with zgrep or zcat. Servers run under systemd also log to journalctl -u .” } }, { “@type”: “Question”, “name”: “Does an ERROR in the log mean my server crashed?”, “acceptedAnswer”: { “@type”: “Answer”, “text”: “No. ERROR usually means one task or plugin failed. If the next line says the plugin is disabling itself, the server is still running and only that feature is gone. Only FATAL, a crash report, or a missing shutdown line point to a full crash.” } }, { “@type”: “Question”, “name”: “How do I read a Java stack trace in a Minecraft log?”, “acceptedAnswer”: { “@type”: “Answer”, “text”: “Start with the exception message on the first line, then read the last Caused by in the chain, which holds the real fault. After that, find the first at frame that names a plugin jar. The jar name and version tell you whose code failed; the line number tells you where.” } }, { “@type”: “Question”, “name”: “How do I fix Address already in use when starting a server?”, “acceptedAnswer”: { “@type”: “Answer”, “text”: “Another process already holds the port. Run ss -ltnp | grep 25565 to find the PID, then either stop that process or change server-port in server.properties. The error(-98) line in the log is the native confirm of a port conflict, not a Java or plugin problem.” } } ] }

Start Reading, Then Start Fixing

Log reading is a skill that pays back immediately. Once you can spot the first error, follow the Caused by chain to the bottom, and map the top plugin frame to a jar and version, most incidents take minutes instead of evenings. The wording in this article came from a real Paper 26.2 build 129 server on Ubuntu 26.04 with Java 25.0.4.1, so it may differ slightly from your version, but the shape never changes: message, cause, frames, thread, plugin. Learn the shape and you can read any log.

Your next step is small and worth doing today: copy logs/latest.log to a dated file, then run grep -n -i -E "error|exception" logs/latest.log and read the first hit properly. If you want a second opinion on what you find, keep our plugin audit guide open beside it, and confirm your backups are current before changing configs. Read the log first. The server already told you what happened.

Generative AI was used to research and add structure to the original content so I can inform you as best as possible. All content has been reviewed by me.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Search

Minecraft Server Tips and Tricks