Skip to content

fix: preserve exception cause in error handling paths - #453

Open
chenjunwenhao wants to merge 1 commit into
alibaba:mainfrom
chenjunwenhao:fix/preserve-exception-cause-in-error-handling
Open

fix: preserve exception cause in error handling paths#453
chenjunwenhao wants to merge 1 commit into
alibaba:mainfrom
chenjunwenhao:fix/preserve-exception-cause-in-error-handling

Conversation

@chenjunwenhao

Copy link
Copy Markdown
Contributor

Summary

Several catch blocks throughout the codebase were silently discarding the original exception when reporting errors through ErrorReporter. This made debugging extremely difficult because the root cause was lost from the exception chain.

Root Cause

The ErrorReporter interface has two report overloads:

  • report(Object catchObj, String errorCode, String reason) — preserves the exception as catchObj, which becomes the cause of the resulting QLRuntimeException
  • report(String errorCode, String reason) — passes null as catchObj, losing the original exception

Multiple catch blocks were using the second overload, causing the caught exception to be completely discarded.

Fixes

File Issue
NewInstanceInstruction.java catch (Exception e) didn't pass e to errorReporter.report()
NewFilledInstanceInstruction.java catch (Exception e) didn't pass e to errorReporter.report()
ForEachInstruction.java catch (UserDefineException e) and catch (Throwable t) didn't pass exceptions
ReflectLoader.unwrapMethodInvokeEx() IllegalArgumentException branch used reportFormat (no cause) instead of reportFormatWithCatch — affects 5 call sites
ThrowUtils.reportUserDefinedException() UserDefineException not passed as catchObj — affects 6 call sites
Express4Runner.parseToDefinitionWithCache() e.getCause() can be null (e.g., InterruptedException), causing new RuntimeException(null)

Tests

  • Added exceptionCausePreservedTest in NewInstanceInstructionTest — verifies that InstantiationException (from instantiating an interface) is preserved as the cause
  • Added parseToDefinitionWithCacheInvalidScriptTest in Express4RunnerTest — verifies error propagation for invalid scripts
  • Added methodInvokeWrongArgTypeCausePreservedTest in Express4RunnerTest — verifies IllegalArgumentException is preserved when calling a method with wrong argument types
  • Fixed MockErrorReporter to propagate catchObj (was hardcoded to null), enabling proper test verification

Test plan

  • New unit tests verify getCause() returns the original exception
  • Existing tests continue to pass (the MockErrorReporter fix is backward-compatible since catchObj is only used for initCause when it's a Throwable)
  • CI pipeline validates full test suite

Several catch blocks were silently discarding the original exception when
reporting errors through ErrorReporter, making debugging extremely difficult.
This fix ensures the caught exception is passed as catchObj so it is
available as the cause of the resulting QLRuntimeException.

Changes:
- NewInstanceInstruction: pass Exception e to errorReporter.report()
- NewFilledInstanceInstruction: pass Exception e to errorReporter.report()
- ForEachInstruction: pass UserDefineException and Throwable to errorReporter
- ReflectLoader.unwrapMethodInvokeEx: pass IllegalArgumentException as catchObj
- ThrowUtils.reportUserDefinedException: pass UserDefineException as catchObj
- Express4Runner.parseToDefinitionWithCache: handle null e.getCause()

Also fixes MockErrorReporter to properly propagate catchObj for testing.
@CLAassistant

CLAassistant commented Jul 4, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants