When a Java try-with-resources block and a resource’s close() method both fail, the exception from the try body stays primary; the close failure is attached to it as a suppressed exception. Read those cleanup failures with getSuppressed(). With multiple resources, Java initializes them from left to right and closes them in reverse order.
What a suppressed exception means
A try-with-resources statement automatically closes each successfully initialized, non-null resource that implements AutoCloseable (including Closeable). A suppressed exception is a secondary failure—typically one thrown while closing a resource—that Java preserves on the primary exception rather than allowing cleanup to replace it.
This is useful because the original failure and the cleanup failure answer different questions: the primary exception explains why the operation failed, while a suppressed exception can explain why cleanup also failed.
Which exception is thrown when the body and close both fail?
The exception thrown by the try body is the one that propagates as the primary exception. If closing a resource also throws, Java adds that close failure to the primary exception’s suppressed-exception list. Oracle’s Java tutorial documents that those failures can be retrieved by calling Throwable.getSuppressed() on the exception thrown by the try block.
For example, if reading a file throws an IOException and closing the reader also throws an IOException, the read failure remains primary. The close failure is available through getSuppressed(); it does not replace the read failure.
How to inspect suppressed exceptions
Call getSuppressed() on the caught primary exception. It returns the suppressed failures associated with that exception. Inspect or log them while preserving and rethrowing the original exception:
Rank #2
try (Reader r = openReader()) {
return read(r);
} catch (Exception primary) {
for (Throwable suppressed : primary.getSuppressed()) {
logger.warn("Resource close failed", suppressed);
}
throw primary;
}
The example catches Exception, matching operations that report exceptions. If your method or API can propagate other kinds of Throwable, choose a handling strategy that fits that contract. Keep diagnostic handling from replacing the primary failure: a logging or cleanup failure in the catch block should not obscure the exception you intended to preserve.
What happens with multiple resources?
Resources are initialized from left to right and closed from right to left. Java’s specification describes multiple resources as behaving like nested try-with-resources statements. A failure during one close does not stop Java from attempting to close the other successfully initialized resources.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Body fails and one or more closes fail
The body’s exception remains primary. Each close failure is suppressed on it as the resources are closed in reverse order. For try (A a = ...; B b = ...), b is closed before a; both close operations are attempted even if closing b fails.
Body succeeds but multiple closes fail
If there is no initializer or body exception, the first close failure becomes the thrown exception. Because closing proceeds from right to left, that is the failure from the rightmost resource whose close operation fails. Failures from later close attempts are suppressed on that primary close failure.
Rank #4
A resource initializer fails
If an initializer throws, Java closes resources that were already initialized. The initializer’s exception remains primary, and any failures encountered while closing those earlier resources are suppressed on it. Resources whose initialization did not complete are not successfully initialized resources to close.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.How try-with-resources compares with a handwritten finally block
| Concern | Try-with-resources | Handwritten finally |
|---|---|---|
| Preserving the original failure | Keeps an earlier initializer or body failure primary and records close failures as suppressed exceptions. | A close failure can replace or mask the earlier failure if the code does not preserve it explicitly. |
| Close order | Closes initialized resources in reverse initialization order. | Depends on the order implemented in the cleanup code. |
| Multiple resources | Attempts to close all successfully initialized resources, even after a close failure. | Requires explicit logic to attempt every close and retain additional failures. |
| Access to cleanup failures | Provides them through Throwable.getSuppressed() on the primary exception. |
Requires explicit handling to retain and expose multiple failures. |
Java SE 7 introduced try-with-resources to support automatic resource management and address exception masking in manual cleanup. For ordinary resources, it is usually clearer to declare them in the try-with-resources header than to reproduce the close and exception-preservation logic in a finally block.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Quick Recap
Best Value
Practical checks when debugging
- Start with the primary exception’s type and stack trace; it represents the initializer, body, or first close failure that propagated.
- Inspect each value returned by
getSuppressed()for failures that happened during resource closure. - For multiple resources, reason about close attempts from right to left, not in declaration order.
- Do not assume that a close failure stopped cleanup of the remaining initialized resources.
- When comparing with manual cleanup, check whether a thrown exception from
close()could mask the operation’s earlier failure.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

