Tomcat 404 After Deploying WAR Context Path Mismatch: Fix It

A practical guide to diagnosing and fixing Tomcat 404 errors after WAR deployment by verifying the effective context path using log and configuration inspection, with manual steps and AI-assisted log reading.

Rao Aadil, India 5 min read

Confirm the 404 is from Tomcat (not a proxy or frontend)

Send a request straight to the Tomcat connector and look at the response headers. Linux, use curl with the -I flag to see the headers without the body:

curl -I http://your-tomcat-host:8080/myapp

Windows PowerShell, use Invoke-WebRequest and print the headers:

$response = Invoke-WebRequest -Uri http://your-tomcat-host:8080/myapp -Method Head -ErrorAction SilentlyContinue
$response.Headers

A Tomcat-generated 404 includes a Server header of Apache-Coyote/1.1 (or a similar Coyote version). If you see nginx, Microsoft-IIS, or another frontend server, the proxy generated the 404 before the request reached Tomcat. The problem is frontend routing, not the WAR deployment.

When you're behind nginx or IIS, compare the frontend access log with Tomcat's access log. Tail Tomcat's access log while repeating the request. Linux:

tail -f $CATALINA_HOME/logs/localhost_access_log.*.txt

Windows PowerShell:

Get-Content "$env:CATALINA_HOME\logs\localhost_access_log.*.txt" -Wait -Tail 100

If the request shows up in the frontend log but not in Tomcat's, the frontend is not forwarding correctly. If it shows up in Tomcat's log with a 404 status, the issue is inside Tomcat.

Doing this with brynko devOps Agent

“The WAR deploys with no error and Manager lists the application as running, but the URL you expect returns 404.”

It checks which context path Tomcat actually assigned - the WAR file name, and any context file under conf/Catalina/localhost that overrides it - and tails the log covering that request, so you find out whether the app is live at a different path or not serving the request at all.

It reads the real state of the server before it says anything, shows you the exact command, and waits for your approval. Windows and Linux, over the SSH access you already have.

Download for WindowsSee what else it does

Find the actual context path Tomcat assigned to the WAR

Tomcat derives the default context path from the name of the file or directory in webapps. The one exception: ROOT maps to /. List the directory to see what Tomcat sees.

Linux:

ls -l $CATALINA_HOME/webapps

Windows PowerShell:

Get-ChildItem "$env:CATALINA_HOME\webapps"

If you deployed myapp.war, the context path is /myapp. If you deployed myapp-1.0.war, it's /myapp-1.0 — even if you always access /myapp.

The deployment log confirms it. Look for a line like Deploying web application archive myapp.war in catalina.out or localhost.log. Linux:

grep -i "Deploying web application" $CATALINA_HOME/logs/catalina.out | tail -20

Windows PowerShell:

Select-String -Path "$env:CATALINA_HOME\logs\catalina.out" -Pattern "Deploying web application" | Select-Object -Last 20

If nothing shows up, check today's localhost log: $CATALINA_HOME/logs/localhost.$(date +%Y-%m-%d).log on Linux or $env:CATALINA_HOME\logs\localhost.$(Get-Date -Format yyyy-MM-dd).log on Windows.

Explicit Context elements can override the default. Check server.xml in $CATALINA_HOME/conf (Linux) or $env:CATALINA_HOME\conf (Windows) for <Context path="/something" docBase="..."> entries. Also look at per-host context files in $CATALINA_HOME/conf/Catalina/localhost/ (or %CATALINA_HOME%\conf\Catalina\localhost\). A file named myapp.xml with a docBase pointing somewhere else makes Tomcat serve that application at /myapp no matter what the WAR file is called.

If you have a tool that can read Tomcat logs and configuration, this is the moment it earns its keep. Ask it to read the Tomcat configuration and show me the effective context path for this WAR, and it returns the relevant lines from catalina.out and any overriding Context entry without you grepping through multiple files manually.

Diagnose common causes of context path mismatch

These patterns produce a deployment that looks fine but 404s on the URL you expect.

WAR file name differs from desired path. myapp.war maps to /myapp; myapp-1.0.war maps to /myapp-1.0. If your build artifact has a version number, Tomcat uses that version number as the context path.

Exploded directory already exists with a different name. Tomcat prefers an exploded directory over a WAR file. An old myapp-old/ directory still sitting in webapps gets deployed instead, and its name becomes the context path. The new WAR is ignored.

A META-INF/context.xml inside the WAR specifies a path attribute. In modern Tomcat (8.0+), the path attribute in an embedded context.xml is ignored unless the Host's copyXML is true. Tomcat logs a warning; the app still deploys under the WAR file name.

A Context element in server.xml or conf/Catalina/[host]/myapp.xml overrides the default naming. In server.xml, <Context path="/foo" docBase="/path/to/war" /> can force a custom path, though it's discouraged. In a per-host file like conf/Catalina/localhost/myapp.xml, the file name myapp is the context path; the path attribute is ignored.

Missing or failed deployment due to exceptions. Tomcat can fail to fully start the web application and keep running, leaving the context unavailable. The manager UI may show the application as deployed, but its servlets never registered. Check catalina.out and localhost.[date].log for stack traces. Linux, tail the latest localhost log:

tail -n 100 $CATALINA_HOME/logs/localhost.$(date +%Y-%m-%d).log

Windows PowerShell:

Get-Content "$env:CATALINA_HOME\logs\localhost.$(Get-Date -Format yyyy-MM-dd).log" -Tail 100

Look for ClassNotFoundException, NoClassDefFoundError, or missing dependency errors.

Fix the context path

Fix the cause, not the symptom.

If the WAR file name is wrong, rename it to match the context path you want. Linux:

mv $CATALINA_HOME/webapps/myapp-1.0.war $CATALINA_HOME/webapps/myapp.war

Windows PowerShell:

Rename-Item "$env:CATALINA_HOME\webapps\myapp-1.0.war" "$env:CATALINA_HOME\webapps\myapp.war"

If an exploded directory is in the way, rename it the same way.

When you need a custom context path that can't be expressed by the file name, create a context file in conf/Catalina/[host]/. Linux:

cat > $CATALINA_HOME/conf/Catalina/localhost/myapp.xml <<'EOF'
<Context docBase="/path/to/your/myapp.war" />
EOF

Windows PowerShell:

Set-Content -Path "$env:CATALINA_HOME\conf\Catalina\localhost\myapp.xml" -Value '<Context docBase="C:\path\to\your\myapp.war" />'

The file name myapp becomes the context path /myapp. The path attribute is neither needed nor honored in this location. Do not put a path attribute in META-INF/context.xml inside the WAR; it will not set the context path in modern Tomcat.

After changing the file name, directory name, or context file, restart Tomcat. Linux with systemd:

sudo systemctl restart tomcat

Or manually:

$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh

Windows, restart the service in PowerShell:

Restart-Service Tomcat9

Or manually:

%CATALINA_HOME%\bin\shutdown.bat
%CATALINA_HOME%\bin\startup.bat

Then request the context path again and check the status code. Linux:

curl -I http://your-tomcat-host:8080/myapp

Windows PowerShell:

$response = Invoke-WebRequest -Uri http://your-tomcat-host:8080/myapp -Method Head -ErrorAction SilentlyContinue
$response.StatusCode

A 200 OK means the app is reachable at the path you wanted. If you still get 404, go back through the context path discovery steps and check the access log for that request.

Prevent future context path surprises

Name final WAR artifacts exactly after the context path you want, no version numbers. Do the rename in your build or release pipeline before deployment.

Tomcat Manager or a scripted deploy can set the context path explicitly. The manager HTTP API takes a custom path parameter and returns a response that says whether the deployment succeeded.

Automate a post-deployment check. A simple script hits the expected context path and verifies the response isn't 404. Linux, combine curl and grep:

curl -s -o /dev/null -w "%{http_code}" http://your-tomcat-host:8080/myapp | grep -q 200 && echo "OK" || echo "Not OK"

Windows PowerShell:

$code = (Invoke-WebRequest -Uri http://your-tomcat-host:8080/myapp -Method Head -ErrorAction SilentlyContinue).StatusCode
if ($code -eq 200) { "OK" } else { "Not OK" }

If your deployment pipeline already calls a log-reading assistant, add a step that asks it to read the Tomcat access log after deploy and report any 404 or error entries for the new context path. That surfaces context path mismatches before a user sees them.

Document the actual context path for each application in a central config repository. The next person shouldn't have to guess.

Related reading

Fix Tomcat 404 from wrong context path

Get step-by-step help to verify the context path Tomcat assigned, find the right logs, and confirm the request after a fix.

An AI teammate that builds, runs, fixes, deploys and operates your software, on your machine and on your servers. It reads the real state of your systems, shows you every command before it runs, and never touches production without your approval.

Works with Docker Docker Compose nginx IIS Tomcat MySQL / MariaDB PostgreSQL Redis Linux servers Windows servers AWS Jenkins Let's Encrypt Node.js Python Java .NET Go PHP
  • Every change asks first, and shows you the exact command or diff before it runs.
  • File edits are snapshotted and reversible. Deleted folders are archived, not removed.
  • Private key material never reaches the model, under any setting.
brynko devOps Agent
Web servers

the site is throwing 502, it was fine yesterday

read the error log checked the vhost listed ports

nginx is fine and so is your app. The error log repeats connect() failed (111: Connection refused) for upstream 127.0.0.1:8019, but nothing is listening there. Your container is bound to 9014. The port changed at the last deploy and the vhost still points at the old one.

point nginx at the right one

one line in the vhost nginx -t passed reloaded

Done. I changed the upstream port in your site config, tested it before applying, and reloaded. The site is returning 200 again.

Fixed · 200 OK

Free download for Windows. 300 free credits on signup, no card, no subscription.

Questions

Common questions

Why does my WAR deploy successfully but return 404 when I access /myapp?
The WAR likely deployed under a different context path than /myapp. Tomcat derives the context path from the WAR file name or exploded directory name, or an explicit Context element overrides it. Check the deployment log for the actual path.
How do I find out what context path Tomcat actually assigned to my WAR?
Look in catalina.out or localhost.log for a line like "Deploying web application archive myapp.war" followed by the context path. You can also list the webapps directory to see the file or folder name that determines the default path.
Where are Tomcat logs located on Linux and Windows?
On Linux, logs are typically in $CATALINA_HOME/logs or $CATALINA_BASE/logs. On Windows, use %CATALINA_HOME%\logs or %CATALINA_BASE%\logs, which contains catalina.out, localhost.log, and access logs.
How can I change the context path of an already deployed WAR?
Rename the WAR file or exploded directory to match the desired context path, then restart Tomcat. Alternatively, create a context file in conf/Catalina/[host]/ with the desired name and a docBase pointing to the WAR, and restart Tomcat.
What is the difference between server.xml context and META-INF/context.xml for setting the context path?
A META-INF/context.xml inside the WAR cannot set the context path; the path attribute is ignored in modern Tomcat. A Context element in server.xml can set a custom path but is discouraged; the recommended location is conf/Catalina/[host]/[appname].xml where the file name is the context path.
Why is my exploded WAR directory being used instead of the WAR file name?
Tomcat prefers an exploded directory over a WAR file with the same base name. If an old directory exists, it will deploy that instead of the new WAR, using the directory name as the context path.
How do I verify that Tomcat is serving my application after changing the context path?
Send a request with curl or Invoke-WebRequest to the new context path and check for a 200 response, not a 404. Also tail the Tomcat access log to confirm the request reaches the correct context path.

Keep reading