ScreenshotNeo

BlogHow-to

How to Fix Tomcat Stuck at Startup

Diagnose Tomcat hangs methodically: verify logs and CATALINA_BASE, isolate deployment failures, capture thread dumps, and apply evidence-based fixes.

By the ScreenshotNeo team29 September 20267 min read

How to Fix Tomcat Stuck at Startup

How to fix Tomcat stuck at startup starts with one distinction: a Java process that remains alive is not automatically hung. After Tomcat finishes starting, its normal lifecycle waits for a shutdown signal in await(). Confirm startup completion in the logs before treating a waiting process as a failure. The official Tomcat architecture guide describes this lifecycle, while the introduction warns that fixes can differ between major versions.

When Tomcat really is stuck, use the last confirmed lifecycle phase, the first complete exception, the effective CATALINA_BASE, and repeated JVM thread dumps to identify whether the wait is in Tomcat, deployment, or an external dependency.

1. Define what “stuck” means

Record these facts before changing configuration:

Trace the last completed lifecycle phase before choosing a fix.
Trace the last completed lifecycle phase before choosing a fix.
  • The exact command, service action, container command, or IDE run configuration.
  • Elapsed time and the timestamp of the last startup log line.
  • Whether a Tomcat JVM exists and whether the service manager reports it as running.
  • Whether the HTTP connector accepts a connection.
  • The Tomcat and Java versions, operating system, Java executable path, CATALINA_HOME, and CATALINA_BASE.

A service wrapper may return while the server JVM continues running. Conversely, a running JVM can be alive while a web application initializer is blocked. Look for the version-appropriate server-startup completion message, not merely a process ID.

2. Find the logs for the active instance

Tomcat uses JULI, its java.util.logging implementation. Begin with the actual instance’s ${catalina.base}/logs directory and the service wrapper’s stdout and stderr capture. Unix startup scripts commonly redirect console output to catalina.out; Windows services use service-specific output files and settings. Confirm the paths used by the service rather than assuming defaults. See the Tomcat logging guide and the historical Tomcat 8 logging guide for the version-specific logging model.

Preserve the first failure

Read from the beginning of the current startup attempt. Save the first exception and every nested Caused by section. The final repeated error is often a consequence. Note the last component, lifecycle event, context path, class, or resource named before progress stops.

JULI configuration is normally in ${catalina.base}/conf/logging.properties. Increase logging narrowly and temporarily if necessary. Enabling DEBUG for every logger can produce megabytes of output and slow startup, as the official documentation cautions.

3. Verify the runtime identity and CATALINA_BASE

The installation directory (CATALINA_HOME) and the runtime instance (CATALINA_BASE) may differ. A common error is editing server.xml under the installation directory while the service reads another base directory.

  1. Inspect the service definition or startup script for the Java path and environment variables.
  2. Print or otherwise record the effective CATALINA_HOME and CATALINA_BASE used by that launch mode.
  3. Check ${catalina.base}/conf/server.xml, web.xml, logging.properties, and the configured log directory.
  4. Verify ownership, permissions, symlinks, and file readability under the service account.
  5. Confirm that the configuration files belong to the same Tomcat major version as the running binaries.

Tomcat documents that it does not fall back from a missing file in CATALINA_BASE/conf to CATALINA_HOME/conf. A missing runtime configuration can therefore stop startup or leave the instance unusable. Configuration changes are read at startup and require a restart.

4. Decide whether deployment is the stalled phase

Tomcat starts server components and containers, then HostConfig responds to lifecycle events to deploy applications. If the final log lines name a context or deployment, inspect that application before changing JVM flags.

Deployment checks

  • Confirm that the WAR, expanded directory, or configured document base exists and is readable.
  • Validate WEB-INF/web.xml and any context XML for malformed syntax.
  • Check that listener and filter classes, plus their transitive libraries, are present.
  • Review application initialization code for database, DNS, filesystem, credential, or network calls.
  • Inspect custom LifecycleListener classes configured in server.xml.

The Tomcat Manager guide lists an unreadable document base, malformed WEB-INF/web.xml, and missing classes during listener or filter initialization as representative deployment failures.

For an isolated test, preserve the artifact and configuration, then temporarily remove or disable one suspect application during a maintenance window. If Tomcat starts, reintroduce the application in a controlled sequence. Avoid casual Manager undeploy operations: the documented operation can delete the WAR, expanded directory, and context XML.

5. Capture JVM evidence when logs stop

If the JVM remains active but no startup progress appears, take at least two thread dumps a short interval apart. Compare identical thread names and stack frames. A stack repeatedly waiting on the same lock, filesystem call, DNS or network operation, class initializer, or application startup method identifies where progress is blocked. One dump is only a snapshot and does not prove deadlock.

Repeated thread dumps reveal waits that a single snapshot can hide.
Repeated thread dumps reveal waits that a single snapshot can hide.

When Manager is installed, enabled, and authorized, its text endpoints provide diagnostics:

curl -u monitor:YOUR_PASSWORD \
  http://localhost:8080/manager/text/threaddump \
  -o tomcat-thread-dump-1.txt

curl -u monitor:YOUR_PASSWORD \
  http://localhost:8080/manager/text/vminfo \
  -o tomcat-vminfo.txt

Do not expose Manager publicly just to collect diagnostics. If it is unavailable, use the thread-dump mechanism supported by your Java release, operating system, and service wrapper, writing the output to a protected file.

6. Map evidence to a fix

Evidence Likely scope Action
Missing or unreadable files under CATALINA_BASE/conf Runtime configuration Correct the active base, restore matching files, fix permissions, and restart.
Parser error in WEB-INF/web.xml Application deployment Fix the XML and redeploy the preserved artifact.
ClassNotFoundException while a listener/filter starts Application dependencies Add the correct library or correct its packaging and class name.
Repeated stack in a custom lifecycle listener Startup customization Inspect its dependencies and external waits; disable only in a controlled test.
Repeated stack in DNS, database, filesystem, or network I/O External dependency Check the named endpoint, credentials, timeout, and service availability.
No progress and no useful exception Unknown Reproduce in staging with identical versions, complete logs, and repeated dumps.

7. Common errors and fixes

“The process is still running, so startup must be hung”

After successful startup, Tomcat normally waits for a shutdown signal. Find the completion message and test the connector before stopping a healthy instance.

“I edited server.xml, but nothing changed”

The service may use another CATALINA_BASE. Inspect the service environment and edit the active base. Restart because Tomcat reads configuration at startup.

“No catalina.out exists”

The wrapper may redirect output elsewhere, or logging may be configured per instance. Inspect the launch definition and ${catalina.base}/logs; on Windows, check the service’s configured stdout and stderr files.

“Deployment stops at one application”

Read the complete first exception for that context. Check document-base permissions, XML syntax, listener/filter classes, and initialization dependencies. Temporarily isolate the application to confirm scope.

“Manager returns 401 or 403”

The Manager user lacks the required role, credentials are wrong, or access is restricted. Correct authorization in a protected environment; do not weaken network controls.

“A thread dump shows waiting threads”

Waiting is not automatically an error. Compare multiple dumps and identify whether the same stack is waiting on a lock or external call. Follow the named resource and its timeout configuration.

8. Performance, reliability, and safe operating practice

  • Capture logs and dumps before repeatedly restarting; repeated restarts can erase the sequence that explains the failure.
  • Use a staging reproduction with the same Tomcat major version, Java runtime, service account, environment, and deployed applications.
  • Prefer a narrow logger change over global DEBUG.
  • Set realistic timeouts for application calls to databases, DNS, filesystems, and HTTP services; investigate the call shown in the stack before adding JVM options.
  • Keep Manager restricted and credentials protected.
  • When comparing launch modes, compare Java executable, environment, service account, base directory, stdout destination, and connector port.

Or skip the browser setup

If you need screenshots of Tomcat status pages, logs, or deployment diagnostics for a ticket or runbook, ScreenshotNeo can capture a URL with one request. It accepts consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing result.

See the ScreenshotNeo API documentation for all options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://tomcat.example.com/manager/html -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://tomcat.example.com/manager/html"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://tomcat.example.com/manager/html' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Use custom headers, cookies, or Authorization for protected diagnostic pages; wait for a selector or network idle when a page renders asynchronously; hide sensitive selectors; and choose PNG, JPEG, WebP, or PDF output. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots each month with no card, and paid plans start at $5 for 3,000.

Create a free ScreenshotNeo account to capture your first diagnostic page.

FAQ

Should I increase Java heap immediately?

No. First establish whether logs show memory pressure or whether a dump identifies a different wait. Apply memory changes only when evidence supports them.

Can a healthy Tomcat look idle?

Yes. After startup, its lifecycle waits for a shutdown signal. Verify the completion log and connector response.

Which Tomcat version should I follow?

Use documentation matching the deployed major version. Tomcat’s introduction notes that issues and solutions can vary between major releases.

How many thread dumps should I collect?

At least two separated by a short interval; three gives a clearer trend when startup timing is uncertain.

What evidence should I attach to a support request?

Include versions, launch mode, effective paths, the complete startup log from that attempt, first exception with causes, and timestamped thread dumps with secrets removed.

Primary references