LuciferYang opened a new issue, #7640:
URL: https://github.com/apache/kyuubi/issues/7640

   ### Description
   
   `DynMethods.UnboundMethod.invoke` unwraps exceptions twice. `invokeChecked` 
already unwraps the `InvocationTargetException` and throws the real exception 
produced by the invoked method, but `invoke` then catches that exception and 
re-throws `e.getCause()` as if `e` were still the wrapper:
   
   ```java
   public <R> R invoke(Object target, Object... args) {
     try {
       return this.invokeChecked(target, args);
     } catch (Exception e) {
       if (e.getCause() instanceof RuntimeException) {
         throw (RuntimeException) e.getCause();
       }
       throw new RuntimeException(e.getCause());
     }
   }
   ```
   
   Two consequences for callers:
   
   - An exception without a cause degrades to `new RuntimeException(null)` — 
the type, message and stack trace of the real failure are all lost. For 
example, a target method throwing `new IOException("connection refused")` 
surfaces as a blank `RuntimeException` with a null message.
   - A `RuntimeException` carrying a cause is silently replaced by its cause: 
`IllegalStateException("...", inner)` surfaces as `inner`, so `catch 
(IllegalStateException)` at the call site misses it.
   
   Both shapes are reachable wherever `invoke` is used across the codebase 
(e.g. `KyuubiBeeLine` error reporting, `EngineTab` install-error reporting, 
`ApplicationMaster`'s exit message), which today can print `null` or a 
misattributed failure instead of the real error.
   
   ### Provenance
   
   The vendored copy diverges from both upstreams: parquet-common 
(`org.apache.parquet.util.DynMethods`, unchanged since PARQUET-777 in 2017) and 
Iceberg (`org.apache.iceberg.common.DynMethods`) both re-throw the 
already-unwrapped `e` itself (`throwIfInstance(e, RuntimeException.class); 
throw new RuntimeException(e);`). The double-unwrap was introduced by the 
vendoring commit db0047d51 ([KYUUBI #3230]) when the upstream helper calls were 
hand-translated into instanceof checks on `e.getCause()`. parquet's own 
`TestDynMethods#testExceptionThrown` pins the correct semantics, which the 
current code fails.
   
   The sibling `DynConstructors.Ctor.newInstance` in the same package already 
implements the correct pattern.
   
   ### Fix direction
   
   Replace the second unwrap with: re-throw `RuntimeException` as-is and wrap 
checked exceptions with the real exception as cause, matching 
`DynConstructors.Ctor.newInstance` and upstream. Add unit tests for 
`org.apache.kyuubi.util.reflect`, which currently has none.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to