apache/druid · error · IllegalStateException
keyColumns[%s] must all be contained in rowSignature[%s]
Error message
keyColumns[%s] must all be contained in rowSignature[%s]
What it means
Key columns must be present in the table's row signature since indexes are built from column functions derived from the signature. The RowBasedIndexedTable constructor validates that keyColumns ⊆ rowSignature column names and throws ISE otherwise.
Source
Thrown at processing/src/main/java/org/apache/druid/segment/join/table/RowBasedIndexedTable.java:91
final List<RowType> table,
final RowAdapter<RowType> rowAdapter,
final RowSignature rowSignature,
final Set<String> keyColumns,
final String version,
@Nullable
final byte[] cacheKey
)
{
this.table = table;
this.rowSignature = rowSignature;
this.columnFunctions =
rowSignature.getColumnNames().stream().map(rowAdapter::columnFunction).collect(Collectors.toList());
this.keyColumns = keyColumns;
this.version = version;
this.cacheKey = cacheKey;
if (!ImmutableSet.copyOf(rowSignature.getColumnNames()).containsAll(keyColumns)) {
throw new ISE(
"keyColumns[%s] must all be contained in rowSignature[%s]",
String.join(", ", keyColumns),
rowSignature
);
}
indexes = new ArrayList<>(rowSignature.size());
for (int i = 0; i < rowSignature.size(); i++) {
final String column = rowSignature.getColumnName(i);
final Index m;
if (keyColumns.contains(column)) {
final ColumnType keyType =
rowSignature.getColumnType(column).orElse(IndexedTableJoinMatcher.DEFAULT_KEY_TYPE);
final RowBasedIndexBuilder builder = new RowBasedIndexBuilder(keyType);
final Function<RowType, Object> columnFunction = columnFunctions.get(i);View on GitHub (pinned to 9b90983fd2)
Solutions
- Fix the keyColumns list to use exact column names from rowSignature
- Verify case-sensitivity of column names (Druid columns are case-sensitive)
- Derive key columns programmatically by checking rowSignature.getColumnNames() first
- Align the signature with the key columns actually needed for the join
Example fix
// before
new RowBasedIndexedTable<>(adapter, signature, version, Set.of("User_Id"), cacheKey);
// after
// signature has column "userId"
new RowBasedIndexedTable<>(adapter, signature, version, Set.of("userId"), cacheKey); Defensive patterns
Strategy: validation
Validate before calling
Set<String> sigCols = ImmutableSet.copyOf(rowSignature.getColumnNames());
if (!sigCols.containsAll(keyColumns)) { throw new IllegalArgumentException("key columns not in signature"); } Try / catch
try { table = new RowBasedIndexedTable<>(...); } catch (ISE e) { /* log and fix keyColumns/signature */ } Prevention
- Derive key column names from the signature instead of hardcoding
- Watch for case mismatches in column names
When it happens
Trigger: Constructing RowBasedIndexedTable (directly or via Builder) passing a keyColumns set containing a column name not in the RowSignature, e.g. a typo or casing mismatch ('UserID' vs 'userId').
Common situations: Typo in key column names; key columns defined for a different schema version; programmatic table construction where signature and keyColumns drift; case-sensitivity mistakes.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Column[%s] has conflicting types [%s] and [%s]
- incrementIndexSchema cannot be null
- String is not a metric column type
- Cannot build hash-join matcher on non-key-based condition: %
- Aggregation [%s] does not support column [%s] of type [%s].
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/63cc255a6ab22cc6.
Report an issue: GitHub.