[Fix][API] Fix validateSingleChoice and extension exceptions bypassing error aggregation#11121
[Fix][API] Fix validateSingleChoice and extension exceptions bypassing error aggregation#11121nzw921rx wants to merge 6 commits into
Conversation
validateSingleChoice was directly throwing OptionValidationException inside collectErrors, which breaks the method's contract of collecting all errors before throwing a single aggregated exception. Changed validateSingleChoice to add errors to the errors list instead of throwing, so that users see all validation failures at once rather than one at a time.
Make it explicit that throwing OptionValidationException aborts remaining validation (fail-fast), while returning false allows the framework to continue collecting other errors.
DanielLeens
left a comment
There was a problem hiding this comment.
Thanks for working on this. I reviewed the full current diff from the actual ConfigValidator.validate(...) call chain instead of treating this as a test-only cleanup.
What this PR fixes
- User pain:
ConfigValidator.validate(...)is supposed to collect as many validation errors as possible and then throw one aggregatedOptionValidationException, but theSingleChoiceOptionbranch was throwing immediately and aborting the rest ofcollectErrors(...). - Fix approach: make
validateSingleChoice(...)append errors into the sharederrorslist instead of throwing immediately, add regression coverage for multiple single-choice failures and mixed error types, and clarify inConditionExtensionJavadoc thatthrowis still fail-fast whilereturn falseparticipates in aggregation. - One-line summary: this restores the real aggregation contract of
ConfigValidator, and I did not find a source-level blocker in the latest head.
Runtime path I checked
Factory / connector config validation
-> ConfigValidator.validate(rule)
-> collectErrors(rule, expression, errors)
-> required option checks
-> SingleChoiceOption checks
-> condition rule checks
-> value constraint checks
-> if errors is not empty
-> build one aggregated OptionValidationException
Key findings
- The normal path really does hit this change. Any factory/connector path that delegates into
ConfigValidator.validate(...)goes throughcollectErrors(...), so this is a real API contract fix. - The change is directionally correct: single-choice validation is now back inside the same aggregation model as required-option and value-constraint failures.
- The
ConditionExtensionJavadoc clarification matters because it keeps the boundary explicit: this PR fixes the single-choice contract violation, but it does not change the intentional fail-fast semantics of custom extensions that choose to throwOptionValidationException. - The new tests cover the right regression surface: multiple single-choice failures together, and mixed single-choice + required + value-constraint failures in one report.
Other reviewer / maintainer input
- There were no prior non-Daniel reviews or comment threads on this PR when I reviewed it, so there was nothing to de-duplicate here.
Testing / stability
- The added tests in
ConfigValidatorTestcover the core contract break directly. - The new tests are structurally stable: pure unit tests, no timing, ports, threads, or external services.
- I did not run local Maven in this batch; this is a source-level PR review only.
- GitHub
Buildwas still queued when I reviewed.
Merge conclusion: can merge
- Blocking items
- None from my side at the source level.
- Suggested follow-up
- No additional source changes needed. Please just let the normal
Buildcheck finish green before merge.
Overall, this is a tight API-layer fix. The changed runtime path is real, the contract improvement is clear, and the regression tests are aimed at the exact failure mode this PR addresses.
|
@davidzollo can you help me review this PR? thank you very much 🚀 |
|
Hi @nzw921rx, from Daniel's side there is no new code-path blocker on the current head, and the current |
…e extension exceptions
…regated error handling
DanielLeens
left a comment
There was a problem hiding this comment.
Thanks for the fix. I re-checked the latest head from ConfigValidator.validate(...) through the extension contract and the added tests, and this looks good to merge from the current source state.
What this PR fixes
- User pain:
validateSingleChoiceandConditionExtensionerrors used to bypass the aggregated validation output, so users only saw partial config feedback at a time. - Fix approach: The PR changes
ConfigValidatorto collect errors first and throw one aggregated validation result, and it clarifies theConditionExtensioncontract. - One-line summary: Config validation is back to the intended “aggregate all errors in one pass” behavior.
Runtime path I traced
Job submission
-> `ConfigValidator.validate(rule)` builds one `errors` list
-> `collectErrors(...)` walks required / optional / conditional / value-constraint checks
-> `OptionValidationException` from extensions is captured and appended
Result
-> validation failures are aggregated again instead of escaping early
Key findings
- The normal submission-time validation path hits this change directly.
- The updated validator now aggregates both
falsereturns andOptionValidationExceptionfailures from extensions. - The contract documentation now matches the implementation better.
Blocking items
None at the source-code level on the current head.
Other review notes
- No additional non-blocking source-level comments from this round.
Compatibility and side effects
- Compatibility: Fully backward compatible. This only fixes validation aggregation behavior.
- Side effects: The extra aggregation cost is tiny and only happens during submission-time validation.
- Error handling / logging: Validation output is now more complete and easier to troubleshoot.
- Tests: The current diff includes regression coverage for the aggregated-failure behavior, and I do not see obvious flaky patterns there.
- Docs: The
ConditionExtensioncontract docs were updated in line with the implementation. - CI: Checks were still pending when I reviewed.
Merge verdict
- I do not see a blocker on the current head. The validation pipeline now aggregates both
SingleChoiceOptionandConditionExtensionfailures as intended.
Purpose of this pull request
Related: #11007
Fix
ConfigValidatorbreaking its error-aggregation contract in two places:validateSingleChoice()previously threwOptionValidationExceptiondirectly, aborting collection of remaining errors.ConditionExtensionimplementations that threwOptionValidationExceptioncaused fail-fast, preventing subsequent validation errors from being reported.Additionally refactors error message formatting to eliminate scattered
String.formatcalls with raw type literals.Changes:
ConfigValidator.validateSingleChoice()— replacethrowwitherrors.add(), accepting aList<String> errorsparameter so single-choice violations participate in error aggregationConfigValidator.collectErrors()— wrap constraint evaluation in try/catch to aggregateOptionValidationExceptionfrom extensions; passerrorslist intovalidateSingleChoice()callsConfigValidator— introduce privateTYPE_*constants and delegate formatting toOptionUtil.formatError()/formatOptionsError(), centralizing the error templateOptionUtil— addformatError()/formatOptionsError()helper methods with a singleERROR_TEMPLATEConditionExtensionjavadoc — update to reflect that thrown exceptions are now caught and aggregated (no longer fail-fast)ConfigValidatorTest— add tests for single-choice error aggregation and extension exception aggregationDoes this PR introduce any user-facing change?
Yes — multiple config validation errors are now reported together instead of stopping at the first single-choice or extension violation. Users see a complete error report on job submission.
How was this patch tested?