{"record":{"id":"d68fb155c9ef44d6","repo":"elastic/elasticsearch","slug":"columnar-field-type-is-not-implemented-yet","errorCode":null,"errorMessage":"ColumNAR field type [{}] is not implemented yet","messagePattern":"ColumNAR field type \\[(.+?)\\] is not implemented yet","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"libs/columnar/src/main/java/org/elasticsearch/columnar/ColumNARDocValuesConsumer.java","lineNumber":97,"sourceCode":"                ColumNARDocValuesFormat.META_EXTENSION\n            );\n            meta = state.directory.createOutput(metaName, state.context);\n            ColumnarCodecUtil.writeHeader(meta, ColumNARDocValuesFormat.META_CODEC, state.segmentInfo.getId(), state.segmentSuffix);\n            success = true;\n        } finally {\n            if (success == false) {\n                IOUtils.closeWhileHandlingException(this);\n            }\n        }\n    }\n\n    @Override\n    public void addBinaryField(FieldInfo field, DocValuesProducer valuesProducer) throws IOException {\n        ColumnarFieldType type = ColumnarFieldType.fromField(field);\n        if (type.isNumeric()) {\n            writeNumericColumn(field, type, () -> ColumnarNumericBinaryDocValues.decodePayloads(valuesProducer.getBinary(field)));\n        } else {\n            throw new UnsupportedOperationException(\"ColumNAR field type [\" + type + \"] is not implemented yet\");\n        }\n    }\n\n    /**\n     * Merge: re-runs the encoder pipeline over the source segments, reading their values in bulk off\n     * disk via {@link ColumnarNumericBinaryDocValues#directValues}. A fresh merge cursor\n     * ({@link DocIDMerger} in merged doc order) is built per pass — count, iterator, values (the skip\n     * index is built inline while the values are encoded, so it needs no pass of its own).\n     */\n    @Override\n    public void mergeBinaryField(FieldInfo field, MergeState mergeState) throws IOException {\n        ColumnarFieldType type = ColumnarFieldType.fromField(field);\n        if (type.isNumeric() == false) {\n            throw new UnsupportedOperationException(\"ColumNAR field type [\" + type + \"] is not implemented yet\");\n        }\n        writeNumericColumn(field, type, () -> mergeCursor(field, mergeState));\n    }\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/columnar/src/main/java/org/elasticsearch/columnar/ColumNARDocValuesConsumer.java#L79-L115","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: mapper tags a text field as columnar STRING\nfield.putAttribute(\"columnar.type\", \"STRING\");\n\n// after: route text fields to a standard doc-values format; keep columnar for numerics only\n// (do not set columnar.type for non-numeric fields)","handlingStrategy":"type-guard","validationCode":"// Before writing, confirm the field type is numeric for ColumNAR\nvoid write(FieldInfo f, DocValuesProducer p) throws IOException {\n    ColumnarFieldType t = ColumnarFieldType.fromField(f);\n    if (!t.isNumeric()) {\n        // route to a different codec / skip; do not call addBinaryField\n        return;\n    }\n    consumer.addBinaryField(f, p);\n}","typeGuard":"static boolean isColumnarNumeric(FieldInfo f) {\n    String v = f.getAttribute(ColumNARDocValuesFormat.TYPE_ATTRIBUTE);\n    return \"LONG\".equals(v) || \"DOUBLE\".equals(v);\n}","tryCatchPattern":"try {\n    consumer.addBinaryField(field, producer);\n} catch (UnsupportedOperationException e) {\n    // ColumNAR cannot write this field type; route it to a standard doc-values format\n    // and log so the mapper configuration gap is visible.\n}","preventionTips":["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."],"tags":["columnar","codec","lucene","unsupported-operation","field-type","write-path"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}