Original exception should be preserved when rethrowing a new exception

Why is this an issue?

When catching an exception and throwing a new one without passing the original exception as a cause, the original stack trace and context are lost.

This leads to:

  • Loss of valuable debugging information (root cause, stack trace)

  • Increased difficulty in diagnosing production issues

  • Reduced observability in logs and monitoring systems

In Java, exception chaining is supported via constructors that accept a Throwable cause or via initCause(). Not using this mechanism breaks the exception propagation chain.

What is the impact?

  • Debugging becomes significantly harder because the root cause is hidden

  • Logging systems and APM tools cannot reconstruct the full failure path

  • Error handling logic higher in the stack may behave incorrectly due to missing context

  • In distributed systems, tracing failures becomes much more complex

What could happen in case of a successful attack?

While this is primarily a reliability issue, in security-sensitive contexts it may:

  • Obscure the origin of failures caused by malicious input

  • Make it harder to detect exploitation patterns

  • Complicate forensic analysis after an incident

Noncompliant Code Example

try {
    process();
} catch (SomeException e) {
    throw new AnotherException("error text");
}

Compliant Code Example

try {
    process();
} catch (SomeException e) {
    throw new AnotherException("error text", e);
}

Hi,

Welcome to the community and thanks for this report!

I think we already have a rule that fits this bill. Can you take a look at java:S1166 and see if it will work for your case?

 
Thx,
Ann

Oh, I see—you’re right.

But please check next example. This rule does not detect that the original exception is not used when CommonException is created.

} catch (Throwable e) {
    if (isRollbackNeeded(e)) {
        try {
            client.rollback(sessionId, "operation failed: " + e.getMessage());
        } catch (Throwable rollbackException) {
            throw rollbackFailed(e, rollbackException);
        }
    }
    throw new CommonException(
            Errors.INTERNAL_SERVER_ERROR.getCode() + ": " +
            Errors.INTERNAL_SERVER_ERROR.getDescription()
    );
}

Hi,

Fair point and thanks for the example. Can you give your context for this? I.e. are you on SonarQube Cloud? SonarQube for IDE (flavor and version)? SonarQube self-managed (flavor and version)?

 
Thx,
Ann

We are using self hosted Community Build
v26.3.0.120487

Hi,

Thanks for confirming you’re on a current version. I’ve flagged this for the language experts.

 
Ann

Hi @mikolg,

Thanks a lot for your finding! I could reproduce the issue, and created a JIRA ticket to fix the problem.