3 min readUpdated 2026-10-10

How to Read Java Stacktraces and Find Root Causes

Learn how to identify Caused by chains, application frames, framework noise, and the line of code most likely responsible for a Java failure.

Maintained by Ali Aygör. Report a correction.

Read exception relationships before individual frames

The first exception often describes the operation that failed, while an explicit Caused by chain records a lower-level failure. Start by listing those relationships, then inspect frames that belong to your application. The deepest cause is an investigation lead, not a guarantee that it explains the complete incident.

Suppressed exceptions are a different relationship. A failure while closing a resource can be attached to the primary exception without replacing it. Searching for the last Exception word in the whole trace can accidentally promote that secondary failure to the root cause.

java.lang.IllegalStateException: Order failed
    at com.acme.orders.OrderService.create(OrderService.java:42)
Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate order_id
    at org.postgresql.Driver.execute(Driver.java:210)
    Suppressed: java.io.IOException: Close failed

Turn this trace into a concrete investigation

In the example, first inspect the order's key, unique constraint and retry behavior. The OrderService frame tells you where the application initiated the operation. The driver frame describes the execution path, while the suppressed close failure is another piece of evidence to retain separately.

Match the trace to the deployed source revision before opening line 42. A line number from another build can lead to unrelated code. Keep the request identifier and timestamp with the trace so you can inspect the input and surrounding log events.

Handle shared and missing frames

An … N more suffix means frames are shared with an enclosing trace. A shortened excerpt can hide the original calling context. Keep the complete cause chain when preparing an internal report rather than deleting framework lines before anyone has inspected them.

Native Method, Unknown Source, module prefixes and generated proxy frames do not identify a normal source-file line. Inspect the nearest useful application frame and the runtime context. Async work may need logs or tracing to connect the failing thread to the originating request.

Use package filtering as a convenience

The analyzer labels candidate application frames by excluding common JDK and framework packages. Custom frameworks, third-party libraries and renamed packages can still appear as candidates. Verify ownership against your repository instead of assuming every remaining frame is your code.

The original trace is retained in the result. Use it to confirm the selected cause, count suppressed exceptions and check that context was not lost. A text heuristic cannot know which layer owns the real corrective action.

Write a useful handoff

Include the exception relationship, candidate application location, deployed version, redacted input shape and one reproducible action. State what you observed separately from your hypothesis. For a duplicate key, distinguish an expected uniqueness rejection from an unwanted retry or collision.

Verify the proposed fix with the same failure condition and a successful control case. Also check that cleanup failures, rollback and retry behavior remain correct; making the visible exception disappear is not always sufficient.

Specifications and references

Continue the investigation

Related tools

Browse all developer tools