apache/seatunnel · warning
Field is null, setting to NULL in prepared statement
Error message
Field {} is null, setting to NULL in prepared statement What it means
In DatabendSinkWriter.processRow(), each field of the row is bound to the PreparedStatement. When a field is null, the writer logs this warning and binds SQL NULL via setNull(i+1, Types.VARCHAR). This is informational: the write continues with a NULL in that column. Note it uses VARCHAR regardless of the column's real type, and will fail if the target column is NOT NULL.
Solutions
- If the column is NOT NULL in Databend, populate the field upstream or set a default value before the sink
- Filter or coalesce null fields with a transform (e.g. CASE/COALESCE in SQL transform)
- Verify field ordering matches the target table column order — nulls in the wrong position indicate mapping misalignment
- If large volumes of this warning appear, disable per-field INFO/WARN logging in processRow — it is very hot-path heavy and slows throughput
Example fix
// before
if (field == null) {
log.warn("Field {} is null, setting to NULL in prepared statement", i + 1);
preparedStatement.setNull(i + 1, java.sql.Types.VARCHAR);
}
// after
if (field == null) {
preparedStatement.setNull(i + 1, columnSqlTypes[i]); // correct JDBC type per column
} Defensive patterns
Strategy: validation
Validate before calling
// pre-validate nulls against target NOT NULL columns
for (int i = 0; i < row.getFields().length; i++) {
if (row.getFields()[i] == null && notNullColumns.contains(i)) {
throw new IllegalArgumentException("Field " + i + " is NULL but column is NOT NULL");
}
} Type guard
boolean hasNulls(SeaTunnelRow row) {
for (Object f : row.getFields()) { if (f == null) return true; }
return false;
} Try / catch
try {
writer.write(row);
} catch (SQLException e) {
if (e.getMessage() != null && e.getMessage().toLowerCase().contains("null")) {
log.error("NOT NULL constraint violated; null field bound to non-nullable column", e);
}
throw e;
} Prevention
- Coalesce/default null columns upstream before the sink
- Match field order to target column order to avoid nulls landing in wrong columns
- Reduce per-field logging in processRow for throughput on large datasets
When it happens
Trigger: Any row containing a null field is processed in the traditional insert path (write -> processTraditionalRow -> processRow).
Common situations: Sparse/optional columns in source data; outer joins producing nulls; missing values in CSV/JSON sources; mapping mistakes leaving fields unpopulated. Fails with NOT NULL violation when the Databend column disallows NULL.
Related errors
- All fields in row are null, skipping
- DATA_TYPE_CAST_FAILED
- SQL_OPERATION_FAILED
- Adding missing fields to SELECT clause
- begin next transaction failed, rollback prepared…
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/a74ea492c24a8a0a.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-databend/src/main/java/org/apache/seatunnel/connectors/seatunnel/databend/sink/DatabendSinkWriter.java:672
fieldTypes[i] = BasicType.DOUBLE_TYPE;
} else if (field instanceof Float) {
fieldTypes[i] = BasicType.FLOAT_TYPE;
} else if (field instanceof Boolean) {
fieldTypes[i] = BasicType.BOOLEAN_TYPE;
} else {
fieldTypes[i] = BasicType.STRING_TYPE;
}
}
return new SeaTunnelRowType(fieldNames, fieldTypes);
}
private void processRow(SeaTunnelRow row) throws SQLException {
log.info("Processing row with {} fields", row.getFields().length);
for (int i = 0; i < row.getFields().length; i++) {
Object field = row.getFields()[i];
if (field == null) {
log.warn("Field {} is null, setting to NULL in prepared statement", i + 1);
preparedStatement.setNull(i + 1, java.sql.Types.VARCHAR);
} else {
log.info(
"Setting parameter {}: {} ({})",
i + 1,
field,
field.getClass().getSimpleName());
preparedStatement.setObject(i + 1, field);
}
}
preparedStatement.addBatch();
log.info("Added row to batch, current batch count: {}", batchCount + 1);
}
private void verifyRawTableData(String rawTableName, String database) throws SQLException {
try (Statement stmt = connection.createStatement();
ResultSet rs =
stmt.executeQuery(View on GitHub (pinned to cf67b549a7)