{"record":{"id":"50d4271113fa967c","repo":"apache/druid","slug":"joining-against-a-array-columns-is-not-supported","errorCode":null,"errorMessage":"Joining against a ARRAY columns is not supported.","messagePattern":"Joining against a ARRAY columns is not supported\\.","errorType":"exception","errorClass":"QueryUnsupportedException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/join/lookup/LookupJoinMatcher.java","lineNumber":109,"sourceCode":"        @Override\n        public Supplier<String> makeDoubleProcessor(BaseDoubleColumnValueSelector selector)\n        {\n          return () -> selector.isNull() ? null : DimensionHandlerUtils.convertObjectToString(selector.getDouble());\n        }\n\n        @Override\n        public Supplier<String> makeLongProcessor(BaseLongColumnValueSelector selector)\n        {\n          return () -> selector.isNull() ? null : DimensionHandlerUtils.convertObjectToString(selector.getLong());\n        }\n\n        @Override\n        public Supplier<String> makeArrayProcessor(\n            BaseObjectColumnValueSelector<?> selector,\n            @Nullable ColumnCapabilities columnCapabilities\n        )\n        {\n          throw new QueryUnsupportedException(\"Joining against a ARRAY columns is not supported.\");\n        }\n\n        @Override\n        public Supplier<String> makeComplexProcessor(BaseObjectColumnValueSelector<?> selector)\n        {\n          return () -> null;\n        }\n      };\n\n  // currentIterator and currentEntry track iteration position through the currently-matched-rows.\n  // 1) currentEntry is the entry that our column selector factory is looking at right now.\n  // 2) currentIterator contains future matches that it _will_ be looking at after nextMatch() is called.\n  @Nullable\n  private Iterator<Map.Entry<String, String>> currentIterator = null;\n  private final SettableSupplier<Pair<String, String>> currentEntry = new SettableSupplier<>();\n\n  private final LookupExtractor extractor;\n  private final JoinConditionAnalysis condition;","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/join/lookup/LookupJoinMatcher.java#L91-L127","documentation":"Lookup joins only support scalar single-value key comparisons. If the join matcher is asked to build a processor for an ARRAY-typed column, it immediately throws QueryUnsupportedException because arrays are not supported as join operands against lookups.","triggerScenarios":"Running a join whose right-hand (lookup) column, or the matched column type, is an ARRAY; the DimensionDictionarySelector's makeArrayProcessor is invoked during selector creation.","commonSituations":"Joining on a column that was ingested as an array type (native array columns) or cast to ARRAY in SQL; schema drift turning a string column into an array.","solutions":["Cast the join column to a scalar type (e.g. VARCHAR) in SQL instead of ARRAY","Re-ingest the data so the join key is a single-value string/long column","Use a different join strategy (not lookup join) if array semantics are truly required"],"exampleFix":"// before\nJOIN lookup l ON t.arr_col = l.k -- arr_col is ARRAY\n// after\nJOIN lookup l ON ARRAY_TO_STRING(t.arr_col, ',') = l.k -- or cast to VARCHAR","handlingStrategy":"type-guard","validationCode":"ColumnCapabilities caps = selectorFactory.getColumnCapabilities(col);\nif (caps != null && caps.getType().equals(ColumnCapabilitiesImpl.CommandType.ARRAY)) throw new IllegalArgumentException(\"array join key unsupported\");","typeGuard":"boolean isNotArray(ColumnCapabilities caps) { return caps == null || !ColumnType.ARRAY.equals(caps.toColumnType()); }","tryCatchPattern":"try { runJoin(query); } catch (QueryUnsupportedException e) { if (e.getMessage().contains(\"ARRAY\")) { /* cast column to scalar and retry */ } }","preventionTips":["Cast array columns to VARCHAR/long before joining","Detect ARRAY-typed join columns at SQL planning time and reject early","Avoid schema drift that converts scalar join keys to arrays"],"tags":["java","join","lookup","array","druid"],"backgroundTag":"unsupported-operation","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"}