Tomcat Troubleshooting Guide

Introduction

Tomcat problems show up as startup failures, 404/500 responses, 502 from Nginx, or silent hangs on shutdown. This chapter maps symptoms to log files, commands, and fixes—a structured companion to Logging and Access Log and the project chapters.

Prerequisites

Step Zero: Quick Health Check

bash
export CATALINA_HOME=/opt/tomcat
./bin/catalina.sh version
curl -I http://127.0.0.1:8080/
ss -tlnp | grep 8080
ls -lt $CATALINA_HOME/logs/ | head -5
CheckHealthy
versionTomcat 10.1.x, JDK 17+
curl200 or expected redirect
ssListener on 8080 (often 127.0.0.1)
logs/Recent dated files updating

Log Files First

SymptomRead first
Won't startlogs/catalina.yyyy-mm-dd.log
App 500logs/localhost.yyyy-mm-dd.log
Deploy failedcatalina.* deploy lines
HTTP access patternlocalhost_access_log.*.txt (if enabled)
Nginx 502/var/log/nginx/error.log + Tomcat catalina
bash
grep -i "SEVERE\|ERROR\|Exception" $CATALINA_HOME/logs/catalina.$(date +%Y-%m-%d).log | tail -20
grep -i "Exception" $CATALINA_HOME/logs/localhost.$(date +%Y-%m-%d).log | tail -20

Startup Failures

Port already in use

text
java.net.BindException: Address already in use
bash
ss -tlnp | grep 8080
# stop Spring Boot, other Tomcat, or Docker container

Fix: stop conflict or change Connector port in server.xml.

JAVA_HOME not set

text
Neither the JAVA_HOME nor the JRE_HOME environment variable is defined

Fix: set JAVA_HOME, restart shell or systemd unit — chapter 04.

server.xml parse error

text
org.xml.sax.SAXParseException

Fix: restore conf/server.xml.bak, validate XML tags, restart.

OutOfMemoryError on startup

Fix: lower app footprint or raise -Xmx in setenv.shJVM tuning.

HTTP 404

CauseFix
Wrong context pathWAR hello.war/hello/..., not /... alone
Deploy incompleteWait; check catalina.log for deploy finished
Wrong WAR namefinalName vs URL
Nginx path strip errorFix proxy_pass slashes — Nginx path rules
App only registers /apicurl full path /context/api
bash
curl -v http://127.0.0.1:8080/blog-api/posts
curl -v -H "Host: app.example.com" http://127.0.0.1/blog-api/posts

HTTP 500

Application exception—stack trace in localhost.*.log.

Common causes:

  • Missing WEB-INF/lib dependency
  • NullPointerException in Servlet
  • Spring Boot misconfiguration on WAR deploy

Fix code or config; redeploy WAR; retest.

502 / 504 from Nginx

CodeMeaningTomcat-side check
502Nginx cannot connectTomcat down; wrong bind (127.0.0.1 vs 0.0.0.0)
504Upstream timeoutSlow app; raise proxy_read_timeout
bash
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/blog-api/posts
sudo tail -20 /var/log/nginx/error.log

503 / Thread Exhaustion

Symptoms: requests hang then fail; CPU moderate; many active threads.

Check server.xml maxThreads, slow DB/API calls, connection leaks.

Mitigation: fix slow path, tune threads/heap — chapter 13; restart Tomcat to recover.

ClassLoader / ClassNotFoundException

PatternFix
jakarta.servlet not found on Tomcat 9Upgrade to Tomcat 10 for Boot 3
javax.servlet on Tomcat 10Migrate app to Jakarta
Duplicate servlet API in WEB-INF/libRemove; use provided
JDBC driver missing for JNDIPut driver in lib/
bash
jar tf target/app.war | grep WEB-INF/lib

JSP / work/ Issues

JSP changes ignored:

bash
$CATALINA_HOME/bin/shutdown.sh
rm -rf $CATALINA_HOME/work/Catalina/localhost/myapp
$CATALINA_HOME/bin/startup.sh

Shutdown Hangs

shutdown.sh waits forever:

  • Shutdown port 8005 blocked or wrong
  • Non-daemon threads in app prevent exit
bash
ss -tlnp | grep 8005
# last resort after investigation:
kill $(pgrep -f catalina)

Fix shutdown port config; fix app thread pools; avoid kill -9 habitually.

Encoding / Garbled Text

  • Connector URIEncoding="UTF-8"server.xml
  • Request setCharacterEncoding("UTF-8") or Filter
  • DB and JSON UTF-8 end-to-end

systemd / Docker

EnvironmentCheck
systemdjournalctl -u tomcat -n 100
Dockerdocker logs tomcat
Wrong userPermission denied on logs/, webapps/

Cross-Track Symptom Index

SymptomSee also
Nginx 502 to 8080Nginx troubleshooting
Spring Boot WAR failschapter 14
Maven WAR emptychapter 08
MySQL connection errorsSpring Boot JDBC

Emergency Recovery Checklist

  1. shutdown.sh or systemctl stop tomcat
  2. Backup conf/ if mid-edit
  3. Read last 50 lines of catalina.* and localhost.*
  4. Fix one issue; start with catalina.sh run foreground
  5. Loopback curl before Nginx
  6. Re-enable Nginx only when Tomcat stable

FAQ

Tomcat starts but all apps 404?

Host appBase wrong; empty webapps/; deploy errors in log.

How to thread dump?

jstack <pid> on Linux when hung—advanced; restart often needed on small VPS.

Two Tomcats after reboot?

Duplicate systemd + manual startup.sh—disable one service.

Works on Windows, fails Linux?

Line endings, case sensitivity, JAVA_HOME, paths with spaces.

Enable remote debug?

CATALINA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 — dev only; firewall port.