apache/seatunnel · error · AssertConnectorException
RULE_VALIDATION_FAILED
RULE_VALIDATION_FAILED
Error message
row :${element} fail rule: ${failRule} What it means
Thrown by AssertSinkWriter.write for each row that violates a configured field-level assert rule. AssertExecutor.fail evaluates the row against AssertFieldRule and, if a rule fails (e.g. field not null, min/max, value range), the writer throws RULE_VALIDATION_FAILED embedding the offending row and the failed rule description.
Source
Thrown at seatunnel-connectors-v2/connector-assert/src/main/java/org/apache/seatunnel/connectors/seatunnel/assertion/sink/AssertSinkWriter.java:96
if (StringUtils.isEmpty(tableName) && StringUtils.isNotEmpty(element.getTableId())) {
tableName = element.getTableId();
} else {
tableName = catalogTableName;
}
if (Objects.isNull(assertFieldRule)) {
assertFieldRule = assertFieldRules.get(tableName);
}
LONG_ACCUMULATOR
.computeIfAbsent(tableName, (k) -> new LongAccumulator(Long::sum, 0))
.accumulate(1);
if (Objects.nonNull(assertFieldRule)) {
ASSERT_EXECUTOR
.fail(element, seaTunnelRowType, assertFieldRule)
.ifPresent(
failRule -> {
throw new AssertConnectorException(
AssertConnectorErrorCode.RULE_VALIDATION_FAILED,
"row :" + element + " fail rule: " + failRule);
});
}
}
@Override
public void close() {
if (!assertRowRules.isEmpty()) {
assertRowRules.entrySet().stream()
.filter(
entry ->
!entry.getValue().isEmpty()
&& (assertRowRules.size() == 1
|| entry.getKey()
.equals(this.catalogTableName)))
.forEach(
entry -> {View on GitHub (pinned to cf67b549a7)
Solutions
- Read failRule in the message to identify which field rule the row violated
- Fix or filter the offending upstream data
- Relax the assert rule (min/max, not-null, allowed values) if it is too strict
- Split data quality checks using a transform before asserting if only some rows should be validated
Example fix
// before rule: field name, assert notNull=true, but row has name=null // after Fix source data, or set notNull=false / add a filter transform for null rows
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate rows against the rule before writing
FailRule fail = AssertExecutor.fail(row, rowType, assertFieldRule).orElse(null);
if (fail != null) { sendToDeadLetterQueue(row, fail); return; } Try / catch
try { writer.write(row); } catch (AssertConnectorException e) { if (RULE_VALIDATION_FAILED.equals(e.getErrorCode())) { log.error("Bad row {}: {}", row, e.getMessage()); /* route to DLQ */ } else throw e; } Prevention
- Profile upstream data (null rates, ranges) before setting assert thresholds
- Use max-allow/fail-on-row settings that tolerate realistic dirty-data rates
- Stage data through a filter/transform to quarantine bad rows before the assert sink
- Keep assert rules aligned with the contract documented for the source
When it happens
Trigger: write(SeaTunnelRow) called with assertFieldRule != null; AssertExecutor.fail returns a non-empty failRule for the row; thrown immediately during data write, failing the job.
Common situations: Data contains nulls or out-of-range values that the assert rule forbids; rule written for different data (e.g. minRow/maxRow too tight); dirty upstream data in a data-quality gate pipeline.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- STREAM_LOAD_FAILED
- STREAM_LOAD_FAILED
- FileConnectorErrorCode.DATA_DESERIALIZE_FAILED
- FileConnectorErrorCode.DATA_DESERIALIZE_FAILED
- DATA_DESERIALIZE_FAILED
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/9c519a339f7872a0.
Report an issue: GitHub.