{"record":{"id":"c4c8faca2797e877","repo":"apache/druid","slug":"expected-complex-type-with-defined-complextypename","errorCode":null,"errorMessage":"Expected complex type with defined complexTypeName, but got [%s]","messagePattern":"Expected complex type with defined complexTypeName, but got \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/frame/field/ComplexFieldReader.java","lineNumber":66,"sourceCode":" * Format:\n * <p>\n * - 1 byte: {@link ComplexFieldWriter#NULL_BYTE} or {@link ComplexFieldWriter#NOT_NULL_BYTE}\n * - 4 bytes: length of serialized complex value, little-endian int\n * - N bytes: serialized complex value\n */\npublic class ComplexFieldReader implements FieldReader\n{\n  private final ComplexMetricSerde serde;\n\n  ComplexFieldReader(final ComplexMetricSerde serde)\n  {\n    this.serde = Preconditions.checkNotNull(serde, \"serde\");\n  }\n\n  public static ComplexFieldReader createFromType(final ColumnType columnType)\n  {\n    if (columnType == null || columnType.getType() != ValueType.COMPLEX || columnType.getComplexTypeName() == null) {\n      throw new ISE(\"Expected complex type with defined complexTypeName, but got [%s]\", columnType);\n    }\n\n    final ComplexMetricSerde serde = ComplexMetrics.getSerdeForType(columnType.getComplexTypeName());\n\n    if (serde == null) {\n      throw new ISE(\"No serde for complexTypeName[%s]\", columnType.getComplexTypeName());\n    }\n\n    return new ComplexFieldReader(serde);\n  }\n\n  @Override\n  public ColumnValueSelector<?> makeColumnValueSelector(Memory memory, ReadableFieldPointer fieldPointer)\n  {\n    return new Selector<>(memory, fieldPointer, serde);\n  }\n\n  @Override","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/frame/field/ComplexFieldReader.java#L48-L84","documentation":"ComplexFieldReader.createFromType builds a reader for a COMPLEX column, which requires a named complex type (complexTypeName) so the matching ComplexMetricSerde can be resolved. It throws ISE when the ColumnType is null, is not ValueType.COMPLEX, or is COMPLEX without a complexTypeName set.","triggerScenarios":"Calling ComplexFieldReader.createFromType(columnType) with a null ColumnType; with a non-complex type (LONG, DOUBLE, STRING, ARRAY); or with a COMPLEX type whose complexTypeName is null, as happens when a complex column is deserialized from a descriptor missing the type name.","commonSituations":"Segment/column schema serialized by a version that did not persist complexTypeName; manually constructed ColumnType instances passed instead of ones parsed from the segment metadata; wiring a complex column through generic field-reader code paths that assume all types.","solutions":["Inspect the ColumnType with ColumnType.toString()/getType() and confirm it is ValueType.COMPLEX with a non-null complexTypeName.","Ensure the column descriptor/serialized payload actually records the complex type name (e.g. hyperUnique, quantilesDoublesSketch).","Route non-complex columns to FieldReaders.create (which dispatches per type) instead of createFromType.","If schema came from old data, re-ingest or upgrade segments so complex type names are present."],"exampleFix":"// before\nif (type.getType() == ValueType.COMPLEX) { reader = ComplexFieldReader.createFromType(type); }\n// after\nif (type != null && type.getType() == ValueType.COMPLEX && type.getComplexTypeName() != null) {\n  reader = ComplexFieldReader.createFromType(type);\n} else {\n  reader = FieldReaders.create(columnName, type);\n}","handlingStrategy":"type-guard","validationCode":"boolean usable = columnType != null && columnType.getType() == ValueType.COMPLEX && columnType.getComplexTypeName() != null;","typeGuard":"boolean isNamedComplex(ColumnType t) { return t != null && t.getType() == ValueType.COMPLEX && t.getComplexTypeName() != null; }","tryCatchPattern":"try { reader = ComplexFieldReader.createFromType(t); } catch (IllegalStateException e) { reader = FieldReaders.create(name, t); }","preventionTips":["Verify complexTypeName is present in serialized column descriptors","Route generic columns through FieldReaders.create, not createFromType","Check ComplexMetrics registrations when reading data written elsewhere"],"tags":["complex-types","column-type","schema"],"backgroundTag":"null-argument","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}