Commit f520a2f
committed
[SPARK-57525][CONNECT] Declarative Pipelines should not throw NoSuchElementException when a run fails without an attached cause
### What changes were proposed in this pull request?
`PipelinesHandler.startRun` rethrows a failed pipeline run to the Spark Connect client via `runFailureEvent.foreach { event => throw event.error.get }`. But `event.error` is `None` for run termination reasons that carry no cause - `UnexpectedRunFailure` and `FailureStoppingFlow` both have `cause = None` - so `event.error.get` raised a `NoSuchElementException`, crashing the handler and hiding the real failure from the client.
This PR extracts the rethrow into `throwRunFailure`: when the failure has a cause it is rethrown unchanged; when it does not, a `SparkException` with a new `PIPELINE_RUN_FAILED` error condition is thrown, carrying the run's termination message. `PIPELINE_RUN_FAILED` (rather than `INTERNAL_ERROR`) is used so that operational outcomes such as `FailureStoppingFlow` are not mislabeled as Spark bugs.
### Why are the changes needed?
A run that fails without an attached cause (e.g. `UnexpectedRunFailure`, or a flow that fails to stop) currently surfaces to the Connect client as an opaque `NoSuchElementException` ("None.get") instead of the actual run-failure message. That masks the real problem and looks like an internal error. These reasons reach this code via the asynchronous `onCompletion` path, where `PipelineExecution.runPipeline`'s own catch never fires.
### Does this PR introduce _any_ user-facing change?
Yes. When a pipeline run fails without an attached cause, the Spark Connect client now receives a `PIPELINE_RUN_FAILED` error carrying the run's termination message (e.g. "Run failed unexpectedly.") instead of a `NoSuchElementException`.
### How was this patch tested?
New `PipelinesHandlerSuite` unit-tests `throwRunFailure` for both cases: the cause-present case rethrows the original cause, and the no-cause case throws a `PIPELINE_RUN_FAILED` `SparkException` carrying the termination message (verified with `checkError`, using the real `UnexpectedRunFailure` and `FailureStoppingFlow` messages). The cause-less termination reasons cannot be triggered deterministically through the end-to-end run path, so the rethrow is unit-tested directly. `SparkThrowableSuite` validates the new error condition.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 4.8)
Closes #56594 from LuciferYang/sdp-run-failure-no-cause.
Authored-by: YangJie <yangjie01@baidu.com>
Signed-off-by: yangjie01 <yangjie01@baidu.com>1 parent 2f1536d commit f520a2f
4 files changed
Lines changed: 101 additions & 3 deletions
File tree
- common/utils/src/main/resources/error
- sql/connect/server/src
- main/scala/org/apache/spark/sql/connect/pipelines
- test/scala/org/apache/spark/sql/connect/pipelines
Lines changed: 6 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6226 | 6226 | | |
6227 | 6227 | | |
6228 | 6228 | | |
| 6229 | + | |
| 6230 | + | |
| 6231 | + | |
| 6232 | + | |
| 6233 | + | |
| 6234 | + | |
6229 | 6235 | | |
6230 | 6236 | | |
6231 | 6237 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4655 | 4655 | | |
4656 | 4656 | | |
4657 | 4657 | | |
| 4658 | + | |
| 4659 | + | |
| 4660 | + | |
| 4661 | + | |
| 4662 | + | |
| 4663 | + | |
4658 | 4664 | | |
4659 | 4665 | | |
4660 | 4666 | | |
| |||
Lines changed: 19 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
563 | 564 | | |
564 | 565 | | |
565 | 566 | | |
566 | | - | |
567 | | - | |
568 | | - | |
| 567 | + | |
569 | 568 | | |
570 | 569 | | |
571 | 570 | | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
572 | 588 | | |
573 | 589 | | |
574 | 590 | | |
| |||
Lines changed: 70 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
0 commit comments