Skip to content

[Fix][API] Fix validateSingleChoice and extension exceptions bypassing error aggregation#11121

Open
nzw921rx wants to merge 6 commits into
apache:devfrom
nzw921rx:fix/config-validator-collect-errors-contract
Open

[Fix][API] Fix validateSingleChoice and extension exceptions bypassing error aggregation#11121
nzw921rx wants to merge 6 commits into
apache:devfrom
nzw921rx:fix/config-validator-collect-errors-contract

Conversation

@nzw921rx

@nzw921rx nzw921rx commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Purpose of this pull request

Related: #11007

Fix ConfigValidator breaking its error-aggregation contract in two places:

  1. validateSingleChoice() previously threw OptionValidationException directly, aborting collection of remaining errors.
  2. ConditionExtension implementations that threw OptionValidationException caused fail-fast, preventing subsequent validation errors from being reported.

Additionally refactors error message formatting to eliminate scattered String.format calls with raw type literals.

Changes:

  • ConfigValidator.validateSingleChoice() — replace throw with errors.add(), accepting a List<String> errors parameter so single-choice violations participate in error aggregation
  • ConfigValidator.collectErrors() — wrap constraint evaluation in try/catch to aggregate OptionValidationException from extensions; pass errors list into validateSingleChoice() calls
  • ConfigValidator — introduce private TYPE_* constants and delegate formatting to OptionUtil.formatError() / formatOptionsError(), centralizing the error template
  • OptionUtil — add formatError() / formatOptionsError() helper methods with a single ERROR_TEMPLATE
  • ConditionExtension javadoc — 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 aggregation

Does 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?

./mvnw test -pl seatunnel-api -Dtest="ConfigValidatorTest" -DfailIfNoTests=false

nzw921rx added 4 commits June 18, 2026 12:59
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.
@github-actions github-actions Bot added the api label Jun 18, 2026
@nzw921rx nzw921rx changed the title Fix/config validator collect errors contract [Fix][API] Fix SingleChoiceOption validation breaking collectErrors aggregation contract Jun 18, 2026
@nzw921rx nzw921rx requested a review from ruanwenjun June 18, 2026 05:06
@nzw921rx nzw921rx self-assigned this Jun 18, 2026
@nzw921rx nzw921rx requested review from chl-wxp and yzeng1618 June 18, 2026 05:06

@DanielLeens DanielLeens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 aggregated OptionValidationException, but the SingleChoiceOption branch was throwing immediately and aborting the rest of collectErrors(...).
  • Fix approach: make validateSingleChoice(...) append errors into the shared errors list instead of throwing immediately, add regression coverage for multiple single-choice failures and mixed error types, and clarify in ConditionExtension Javadoc that throw is still fail-fast while return false participates 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

  1. The normal path really does hit this change. Any factory/connector path that delegates into ConfigValidator.validate(...) goes through collectErrors(...), so this is a real API contract fix.
  2. The change is directionally correct: single-choice validation is now back inside the same aggregation model as required-option and value-constraint failures.
  3. The ConditionExtension Javadoc 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 throw OptionValidationException.
  4. 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 ConfigValidatorTest cover 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 Build was still queued when I reviewed.

Merge conclusion: can merge

  1. Blocking items
  • None from my side at the source level.
  1. Suggested follow-up
  • No additional source changes needed. Please just let the normal Build check 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.

@nzw921rx

Copy link
Copy Markdown
Collaborator Author

@davidzollo can you help me review this PR? thank you very much 🚀

@DanielLeens

Copy link
Copy Markdown
Contributor

Hi @nzw921rx, from Daniel's side there is no new code-path blocker on the current head, and the current Build check is green as well. Since there hasn't been a new commit after my approval, I won't restate a fresh full review here, but this PR still looks ready for maintainer pickup from my side.

@nzw921rx nzw921rx requested a review from davidzollo June 22, 2026 04:01
@nzw921rx nzw921rx changed the title [Fix][API] Fix SingleChoiceOption validation breaking collectErrors aggregation contract [Fix][API] Fix validateSingleChoice and extension exceptions bypassing error aggregation Jun 22, 2026

@DanielLeens DanielLeens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: validateSingleChoice and ConditionExtension errors used to bypass the aggregated validation output, so users only saw partial config feedback at a time.
  • Fix approach: The PR changes ConfigValidator to collect errors first and throw one aggregated validation result, and it clarifies the ConditionExtension contract.
  • 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 false returns and OptionValidationException failures 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 ConditionExtension contract 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 SingleChoiceOption and ConditionExtension failures as intended.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants