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

  1. Do not route non-numeric fields through the ColumNAR codec; map text/keyword fields with a different doc_values format.
  2. If you are developing ColumNAR, implement the STRING write path in addBinaryField (extend the dispatch) before exposing STRING in the mapper.
  3. Verify the field's columnar.type attribute — it should be LONG or DOUBLE for any field handled by this consumer.
  4. 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

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


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/d68fb155c9ef44d6. Report an issue: GitHub.