apache/druid · error · IllegalStateException
Missing type for column [%s]
Error message
Missing type for column [%s]
What it means
StageDefinition's constructor verifies that every column in the stage's RowSignature has a known type. If signature.getColumnType(columnName) is empty for any column, the stage is malformed and ISE("Missing type for column [%s]") is thrown. Downstream frame serialization and shuffle logic require fully-typed signatures.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/kernel/StageDefinition.java:143
this.broadcastInputNumbers = (IntSet) broadcastInputNumbers;
} else {
this.broadcastInputNumbers = new IntAVLTreeSet(broadcastInputNumbers);
}
this.processor = Preconditions.checkNotNull(processor, "processor");
this.signature = Preconditions.checkNotNull(signature, "signature");
this.shuffleSpec = shuffleSpec;
this.maxWorkerCount = maxWorkerCount;
this.shuffleCheckHasMultipleValues = shuffleCheckHasMultipleValues;
this.frameReader = Suppliers.memoize(() -> FrameReader.create(signature))::get;
if (mustGatherResultKeyStatistics() && shuffleSpec.clusterBy().isEmpty()) {
throw new IAE("Cannot shuffle with spec [%s] and nil clusterBy", shuffleSpec);
}
for (final String columnName : signature.getColumnNames()) {
if (!signature.getColumnType(columnName).isPresent()) {
throw new ISE("Missing type for column [%s]", columnName);
}
}
for (final int broadcastInputNumber : this.broadcastInputNumbers) {
if (broadcastInputNumber < 0 || broadcastInputNumber >= inputSpecs.size()) {
throw new ISE("Broadcast input number out of range [%s]", broadcastInputNumber);
}
}
}
public static boolean mustGatherResultKeyStatistics(@Nullable final ShuffleSpec shuffleSpec)
{
return shuffleSpec != null
&& shuffleSpec.kind() == ShuffleKind.GLOBAL_SORT
&& ((GlobalSortShuffleSpec) shuffleSpec).mustGatherResultKeyStatistics();
}
public static StageDefinitionBuilder builder(final int stageNumber)View on GitHub (pinned to 9b90983fd2)
Solutions
- Declare the type when building the signature: signatureBuilder.add(columnName, ColumnType.LONG) (or the correct type)
- Trace where the named column enters the signature and add its SqlType/ColumnType at that point
- Check custom extension processors that produce output columns and ensure they extend the signature with types
Example fix
// before
RowSignature.Builder.add("cnt");
// after
RowSignature.Builder.add("cnt", ColumnType.LONG); Defensive patterns
Strategy: validation
Validate before calling
for (String col : signature.getColumnNames()) {
if (!signature.getColumnType(col).isPresent()) {
throw new IllegalStateException("Column missing type: " + col);
}
} Try / catch
try { StageDefinition def = builder.build(); } catch (IllegalStateException e) { log.error("Untyped column in signature: {}", e.getMessage()); } Prevention
- Use RowSignature.Builder.add(name, ColumnType) — never the typeless overload
- Have processors declare output column types when they append columns
- Assert signature completeness in unit tests for custom processors
When it happens
Trigger: Creating a StageDefinition whose RowSignature contains a column added without a type (e.g. via RowSignature.Builder.add(col) without the type argument, or a column synthesized by a processor that never set its type).
Common situations: Custom aggregation/processor extensions appending output columns without declaring their SqlType, or building signatures dynamically from input data where a column's type could not be inferred.
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]
- Aggregation [%s] does not support column [%s] of type [%s].
- Unknown schema %s
- Invalid Struct type.
- Unknown
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/650b788592d9fb9c.
Report an issue: GitHub.