apache/seatunnel · error · MilvusConnectorException
FIELD_IS_NULL
FIELD_IS_NULL
Error message
FIELD_IS_NULL
What it means
MilvusSinkConverter.buildMilvusData throws FIELD_IS_NULL when a SeaTunnelRow field is null and the corresponding column does not permit null values. Milvus requires the primary key and partition key to be non-null; other fields are only nullable if declared nullable in the catalog schema or if the 'enable.nullable-field' option is turned on. The error message carries the offending field name.
Solutions
- Filter out or default null values upstream before writing to the Milvus sink (e.g. a SQL transform with COALESCE/NVL).
- Set the sink option 'enable.nullable-field' = true if the target Milvus collection truly allows null for this field.
- Verify the catalog table schema marks the column nullable so allowNullableField passes.
- Ensure the primary key and partition key columns are never null in your data.
Example fix
// before (row with null field) row.setField(2, null); // field 'embedding_desc' is not nullable // after row.setField(2, defaultValueIfNull(actualValue)); // or set enable.nullable-field=true
Defensive patterns
Strategy: validation
Validate before calling
// before writing to Milvus sink
for (int i = 0; i < rowType.getFieldNames().length; i++) {
if (element.getField(i) == null && !nullableFields.contains(rowType.getFieldNames()[i])) {
throw new IllegalArgumentException("Field " + rowType.getFieldNames()[i] + " must not be null");
}
} Try / catch
try { sinkWriter.write(row); } catch (MilvusConnectorException e) { if (MilvusConnectionErrorCode.FIELD_IS_NULL.equals(e.getErrorCode())) { log.warn("Null non-nullable field: {}", e.getMessage()); } else { throw e; } } Prevention
- Coalesce nulls to defaults in a SQL transform before the Milvus sink
- Enable enable.nullable-field only when the Milvus collection schema actually permits nulls
- Never allow null primary/partition key columns from upstream sources
When it happens
Trigger: Writing a row whose field value is null for a column that is not nullable, is the primary key, or is the partition key, while allowNullableField(column, primaryKey, partitionKeyField, enableNullableField) returns false in buildMilvusData.
Common situations: Upstream source produces nulls (e.g. missing JSON keys, LEFT JOIN misses) that are passed straight into the Milvus sink; writing to a Milvus collection whose primary/partition key column receives null; user forgot to enable the nullable-field option even though the collection schema allows nulls.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- create index failed, maybe index already exists
- Not support convert to milvus type, sqlType is
- NOT_SUPPORT_TYPE
- WRITE_DATA_FAIL
- Airtable API rate limit reached, retry
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/fc8d78b338e39cfc.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-milvus/src/main/java/org/apache/seatunnel/connectors/seatunnel/milvus/utils/sink/MilvusSinkConverter.java:333
String partitionKeyField = getPartitionKeyField(catalogTable, config);
JsonObject data = new JsonObject();
Gson gson = new Gson();
for (int i = 0; i < seaTunnelRowType.getFieldNames().length; i++) {
String fieldName = seaTunnelRowType.getFieldNames()[i];
Boolean isJson = jsonFields.contains(fieldName);
if (autoId && isPrimaryKeyField(primaryKey, fieldName)) {
continue; // if create table open AutoId, then don't need insert data with
// primaryKey field.
}
SeaTunnelDataType<?> fieldType = seaTunnelRowType.getFieldType(i);
Object value = element.getField(i);
if (value == null) {
Column column = catalogTable.getTableSchema().getColumn(fieldName);
if (!allowNullableField(
column, primaryKey, partitionKeyField, enableNullableField)) {
throw new MilvusConnectorException(
MilvusConnectionErrorCode.FIELD_IS_NULL, fieldName);
}
if (dynamicField != null
&& dynamicField.equals(fieldName)
&& config.get(ENABLE_DYNAMIC_FIELD)) {
continue;
}
data.add(fieldName, JsonNull.INSTANCE);
continue;
}
// if the field is dynamic field, then parse the dynamic field
if (dynamicField != null
&& dynamicField.equals(fieldName)
&& config.get(ENABLE_DYNAMIC_FIELD)) {
JsonObject dynamicData = gson.fromJson(value.toString(), JsonObject.class);
dynamicData
.entrySet()
.forEach(View on GitHub (pinned to cf67b549a7)