apache/druid · error · IllegalArgumentException
Column %d must have a name
Error message
Column %d must have a name
What it means
When merging column updates, each update column must carry a non-empty name so the merge can locate the existing column it replaces (or append it as new). An unnamed column cannot be positioned in the merged list, so mergeColumns() throws IAE with the 1-based column position.
Source
Thrown at server/src/main/java/org/apache/druid/catalog/model/TableDefn.java:171
* Columns are matched by name. If the column exists, then it is updated. If
* the column does not exist, then the new column is appended to the existing
* list. This merge operation cannot remove columns or change order.
*/
public List<ColumnSpec> mergeColumns(List<ColumnSpec> columns, List<ColumnSpec> update)
{
if (update == null || update.isEmpty()) {
return columns;
}
Map<String, Integer> original = new HashMap<>();
for (int i = 0; i < columns.size(); i++) {
original.put(columns.get(i).name(), i);
}
List<ColumnSpec> merged = new ArrayList<>(columns);
for (int i = 0; i < update.size(); i++) {
ColumnSpec col = update.get(i);
String colName = col.name();
if (Strings.isNullOrEmpty(colName)) {
throw new IAE("Column %d must have a name", i + 1);
}
Integer index = original.get(col.name());
if (index == null) {
merged.add(col);
} else {
merged.set(index, mergeColumn(columns.get(index), col));
}
}
return merged;
}
private ColumnSpec mergeColumn(ColumnSpec existingCol, ColumnSpec update)
{
ColumnSpec revised = existingCol.merge(columnProperties, update);
revised.validate();
validateColumn(revised);
return revised;
}View on GitHub (pinned to 9b90983fd2)
Solutions
- Set a non-empty name on every column in the update spec before merging
- Fix the JSON payload so each update column object includes a "name" field
- Reject/validate the update payload client-side before calling merge
Example fix
// before
List<ColumnSpec> update = Collections.singletonList(new ColumnSpec(null, "long"));
spec.merge(base, new TableSpec(null, null, update), mapper);
// after
List<ColumnSpec> update = Collections.singletonList(new ColumnSpec("metric1", "long"));
spec.merge(base, new TableSpec(null, null, update), mapper); Defensive patterns
Strategy: validation
Validate before calling
for (int i = 0; i < update.columns().size(); i++) {
if (Strings.isNullOrEmpty(update.columns().get(i).name())) {
throw new IllegalArgumentException("update column " + (i + 1) + " has no name");
}
} Type guard
boolean allColumnsNamed(List<ColumnSpec> cols) {
return cols != null && cols.stream().allMatch(c -> c.name() != null && !c.name().isEmpty());
} Try / catch
try { return base.merge(base, update, mapper); } catch (IllegalArgumentException e) { if (e.getMessage().contains("must have a name")) { /* repair update columns */ } else { throw e; } } Prevention
- Require name on every column constructor/DTO
- Reject anonymous columns at deserialization time
- Include column-name checks in your update-payload builder
When it happens
Trigger: Calling TableSpec.merge() (via mergeColumns) with an update spec whose columns list contains a ColumnSpec with a null or empty name; the message reports the 1-based position of the offending column.
Common situations: Constructing update columns programmatically and forgetting to set the name; JSON update payloads with a missing/empty "name" field; partial column definitions copied from a template.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Column name is required
- The update type must be null or [%s]
- The table type is required.
- Database schema is required
- Table name is required
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/acf81bbd40dd134c.
Report an issue: GitHub.