9

I'm trying to debug issue with an app that throws exception, and the stack trace is cut off even when I use -XX:MaxJavaStackTraceDepth=16777216 (or any other value there, like -1 or 2048).

It is cut off like this:

Caused by: java.lang.IllegalStateException: unexpected message type: DefaultLastHttpContent
    at io.netty.handler.codec.http.HttpObjectEncoder.encode(HttpObjectEncoder.java:124)
    at io.netty.handler.codec.http.HttpClientCodec$Encoder.encode(HttpClientCodec.java:167)
    at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:89)
    ... 89 more

I want to see more stack trace elements instead of ... 89 more how to achieve that?

This is in Java 8 using SLF4J + Logback for logging with the following configuration:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>
    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Krzysztof Krasoń
  • 26,515
  • 16
  • 89
  • 115
  • I expect it says that because there's a chained exception that has overlapping stack frames. The duplicate frames are elided. – John Kugelman May 12 '20 at 12:26
  • @JohnKugelman Is there a way to avoid that? Some runtime option? And how it is possible to have chained exception with overlapping stack frames? I checked the exception before the `Caused by` and it doesn't overlap with any element below it. – Krzysztof Krasoń May 12 '20 at 14:39
  • 1
    No, `-XX:-OmitStackTraceInFastThrow` doesn't change that, and I think it would work only if I had this problem in recurring exceptions, but I see this also in first exception thrown. – Krzysztof Krasoń May 12 '20 at 15:11
  • 1
    How do you conclude that there are no overlapping stack frames? The overlapping frames are the 89 frames that have not been printed. – Holger May 12 '20 at 15:47
  • @Holger Ok, there might be overlapping, but how should I know that? At what point they overlap? Shouldn't there be at least one element that exists in both places? I just can't believe that Java would ship with something that just truncates stacktraces without allowing developer to see where they overlap. – Krzysztof Krasoń May 12 '20 at 15:55
  • 1
    Actually, this feature is intuitively understandable, as long as you don’t look at the cause only, like you do in this question. I’m quiet sure that there *are* entries for `io.netty.handler.codec.MessageToMessageEncoder.write(…)` in the stack traces of both exceptions, as the caller of the `write` method must be the first identical entry. – Holger May 12 '20 at 16:02
  • @Holger OK, I see a call like that, at the top of stack trace: `at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:107)`, so what you are saying is that after the `MessageToMessageEncoder.write(MessageToMessageEncoder.java:89)` I'll have the one at line 107? – Krzysztof Krasoń May 12 '20 at 16:08
  • 3
    Basically, this means that `write` calls `encode` in line 89, which produced the first exception, the `IllegalStateException`, then, `write` caught the exception and constructed a new exception in line 107, which was then thrown. It’s typical that the exception handler that throws a wrapping exception is on a different line than the call that produced the first exception. Then, all other entries representing the caller of that method are identical. – Holger May 12 '20 at 16:16
  • @JohnKugelman How is it different – Michael May 12 '20 at 18:42
  • 2
    @Michael the `OmitStackTraceInFastThrow` option affects whether the stack traces are actually recorded. As explained in my answer, this question is about how the stack traces are printed, while they still are fully recorded. – Holger May 13 '20 at 07:52
  • Does this answer your question? [How to read the full stacktrace in Java where it says e.g. "... 23 more"](https://stackoverflow.com/questions/2970361/how-to-read-the-full-stacktrace-in-java-where-it-says-e-g-23-more) – Philippe Cloutier May 16 '23 at 21:53

1 Answers1

9

When you have an example program like this:

public class ExceptionExample {
    public static void main(String[] args) {
        foo();
    }
    static void foo() {
        bar();
    }
    static void bar() {
        try { baz(); }
        catch(Exception ex) { throw new RuntimeException("secondary", ex); }
    }
    static void baz() {
        throw new RuntimeException("primary");
    }
}

It will produce:

Exception in thread "main" java.lang.RuntimeException: secondary
    at ExceptionExample.bar(ExceptionExample.java:11)
    at ExceptionExample.foo(ExceptionExample.java:7)
    at ExceptionExample.main(ExceptionExample.java:4)
Caused by: java.lang.RuntimeException: primary
    at ExceptionExample.baz(ExceptionExample.java:14)
    at ExceptionExample.bar(ExceptionExample.java:10)
    ... 2 more

Since within bar, the method invocation that led to an exception is on a different line than the construction of the wrapping secondary exception, it appears in both stack traces. The call chain of bar, i.e. main > foo, is identical and hence, omitted in the cause.

The stack trace still is recorded in the throwable, only the printing is affected. That’s why JVM options regarding the recording do not affect this. E.g.

public class ExceptionExample {
    public static void main(String[] args) {
        try {
            foo();
        }
        catch(Throwable t) {
            for(; t != null; t = t.getCause()) {
                System.err.println(t);
                for(StackTraceElement e: t.getStackTrace())
                    System.err.println("\tat "+e);
            }
        }
    }
    static void foo() {
        bar();
    }
    static void bar() {
        try { baz(); }
        catch(Exception ex) { throw new RuntimeException("secondary", ex); }
    }
    static void baz() {
        throw new RuntimeException("primary");
    }
}

will print

java.lang.RuntimeException: secondary
    at ExceptionExample.bar(ExceptionExample.java:20)
    at ExceptionExample.foo(ExceptionExample.java:16)
    at ExceptionExample.main(ExceptionExample.java:5)
java.lang.RuntimeException: primary
    at ExceptionExample.baz(ExceptionExample.java:23)
    at ExceptionExample.bar(ExceptionExample.java:19)
    at ExceptionExample.foo(ExceptionExample.java:16)
    at ExceptionExample.main(ExceptionExample.java:5)
Holger
  • 285,553
  • 42
  • 434
  • 765