Suppose main() is frame 1 and the method that ultimately throws the exception is frame 10. Why does a stack trace print the exception message followed by frames 10, 9, 8, and so on down to 1? With nested exceptions, it can look like this: an exception at frame 4 shows 4 through 1, another at frame 7 shows 7 through 4, and the final exception at frame 10 shows 10 through 7. Wouldn't it be clearer to start with the deepest/root failure at the top, print frames 10 through 1, and avoid repeating shared frames such as 4 and 7?
2 Answers
The frame order is intentional: the first frame is where that exception was thrown, and the following frames show how execution reached that point. Reading downward follows the call path back toward the original caller. For nested exceptions, each exception has its own stack, so shared frames can appear repeatedly; that preserves the exact stack associated with every exception rather than trying to merge them into one reconstructed trace.
A stack trace describes the particular exception that was caught and printed. If the exception at frame 4 is an IllegalArgumentException, its own trace is 4, 3, 2, 1. A different exception may have been caught earlier and attached as its cause, so the output prints the outer exception first and then the cause chain. Printing the exception from frame 10 as though it were the one caught at frame 4 could be misleading, even if the deeper exception is ultimately the root cause.

That explains the separate traces, but the repeated transition between frames still feels unintuitive. I would personally find the deepest cause first and a merged path easier to scan.