elastic/elasticsearch · error · UnsupportedOperationException
ColumNAR field type [{}] is not implemented yet
Error message
ColumNAR field type [{}] is not implemented yet What it means
Thrown by ColumNARDocValuesConsumer.addBinaryField during segment flush when a field's ColumnarFieldType (read from the field's columnar.type attribute) is not numeric. ColumNAR today implements only LONG and DOUBLE columns; STRING is declared in the enum but the write path is not built. There is no delegate fallback — an unsupported type is a hard error per the library's non-negotiable rules. UnsupportedOperationException (not IllegalArgumentException) signals 'not yet implemented' rather than 'invalid argument'.
Source
Thrown at libs/columnar/src/main/java/org/elasticsearch/columnar/ColumNARDocValuesConsumer.java:97
ColumNARDocValuesFormat.META_EXTENSION
);
meta = state.directory.createOutput(metaName, state.context);
ColumnarCodecUtil.writeHeader(meta, ColumNARDocValuesFormat.META_CODEC, state.segmentInfo.getId(), state.segmentSuffix);
success = true;
} finally {
if (success == false) {
IOUtils.closeWhileHandlingException(this);
}
}
}
@Override
public void addBinaryField(FieldInfo field, DocValuesProducer valuesProducer) throws IOException {
ColumnarFieldType type = ColumnarFieldType.fromField(field);
if (type.isNumeric()) {
writeNumericColumn(field, type, () -> ColumnarNumericBinaryDocValues.decodePayloads(valuesProducer.getBinary(field)));
} else {
throw new UnsupportedOperationException("ColumNAR field type [" + type + "] is not implemented yet");
}
}
/**
* Merge: re-runs the encoder pipeline over the source segments, reading their values in bulk off
* disk via {@link ColumnarNumericBinaryDocValues#directValues}. A fresh merge cursor
* ({@link DocIDMerger} in merged doc order) is built per pass — count, iterator, values (the skip
* index is built inline while the values are encoded, so it needs no pass of its own).
*/
@Override
public void mergeBinaryField(FieldInfo field, MergeState mergeState) throws IOException {
ColumnarFieldType type = ColumnarFieldType.fromField(field);
if (type.isNumeric() == false) {
throw new UnsupportedOperationException("ColumNAR field type [" + type + "] is not implemented yet");
}
writeNumericColumn(field, type, () -> mergeCursor(field, mergeState));
}
View on GitHub (pinned to db6a809a66)
Solutions
- Do not route non-numeric fields through the ColumNAR codec; map text/keyword fields with a different doc_values format.
- If you are developing ColumNAR, implement the STRING write path in addBinaryField (extend the dispatch) before exposing STRING in the mapper.
- Verify the field's columnar.type attribute — it should be LONG or DOUBLE for any field handled by this consumer.
- As a temporary measure, exclude the offending field from columnar storage via the mapper configuration.
Example fix
// before: mapper tags a text field as columnar STRING
field.putAttribute("columnar.type", "STRING");
// after: route text fields to a standard doc-values format; keep columnar for numerics only
// (do not set columnar.type for non-numeric fields) Defensive patterns
Strategy: type-guard
Validate before calling
// Before writing, confirm the field type is numeric for ColumNAR
void write(FieldInfo f, DocValuesProducer p) throws IOException {
ColumnarFieldType t = ColumnarFieldType.fromField(f);
if (!t.isNumeric()) {
// route to a different codec / skip; do not call addBinaryField
return;
}
consumer.addBinaryField(f, p);
} Type guard
static boolean isColumnarNumeric(FieldInfo f) {
String v = f.getAttribute(ColumNARDocValuesFormat.TYPE_ATTRIBUTE);
return "LONG".equals(v) || "DOUBLE".equals(v);
} Try / catch
try {
consumer.addBinaryField(field, producer);
} catch (UnsupportedOperationException e) {
// ColumNAR cannot write this field type; route it to a standard doc-values format
// and log so the mapper configuration gap is visible.
} Prevention
- Only tag numeric fields (LONG/DOUBLE) with the columnar.type attribute.
- Do not enable the ColumNAR codec for indexes with text/keyword fields mapped to columnar storage.
- In the mapper, guard the attribute assignment on ColumnarFieldType.isNumeric().
- Track STRING support status before exposing it in the mapper layer.
When it happens
Trigger: Indexing a field whose mapper set the columnar.type attribute to STRING (or any future non-numeric type) and then triggering a segment flush that calls addBinaryField for that field. Also reproducible by manually tagging a FieldInfo with a non-numeric ColumnarFieldType and writing through this consumer.
Common situations: An integration enables the ColumNAR codec for an index that contains keyword/text fields mapped to columnar storage before STRING support ships. A custom mapper incorrectly tags a binary field as STRING. Running a newer codec against a field type that the build's enum knows but the consumer doesn't write.
Related errors
- blockSize must be a power of 2 in [{}, {}], got: {}
- ${className} does not support remove()
- ${className} does not support removeAll()
- ${className} does not support retainAll()
- ${className} does not support putAll()
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/d68fb155c9ef44d6.
Report an issue: GitHub.