OtterMind/Chat2DB · error · IllegalArgumentException

DM index must contain at least one named column

Error message

DM index must contain at least one named column

What it means

Thrown by DMIndexTypeEnum.buildIndexColumn (inside DMIndexTypeEnum) when, after iterating every TableIndexColumn, none had a non-blank columnName. The guard prevents emitting an index DDL fragment with an empty column list "()", which would be invalid SQL.

Source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-dm/src/main/java/ai/chat2db/plugin/dm/enums/type/DMIndexTypeEnum.java:109

    }


    private String buildIndexColumn(TableIndex tableIndex) {
        StringBuilder script = new StringBuilder();
        script.append("(");
        boolean hasColumn = false;
        for (TableIndexColumn column : tableIndex.getColumnList()) {
            if (StringUtils.isNotBlank(column.getColumnName())) {
                hasColumn = true;
                script.append(DMIdentifierProcessor.INSTANCE.quoteIdentifierAlways(column.getColumnName()));
                if (!StringUtils.isBlank(column.getAscOrDesc()) && !PRIMARY_KEY.equals(this)) {
                    script.append(" ").append(DMSqlGuards.requireAscOrDesc(column.getAscOrDesc()));
                }
                script.append(",");
            }
        }
        if (!hasColumn) {
            throw new IllegalArgumentException("DM index must contain at least one named column");
        }
        script.deleteCharAt(script.length() - 1);
        script.append(")");
        return script.toString();
    }

    private String buildIndexName(TableIndex tableIndex) {
        return qualifiedName(tableIndex.getSchemaName(), tableIndex.getName());
    }

    public String buildModifyIndex(TableIndex tableIndex) {
        if (EditStatusEnum.DELETE.name().equals(tableIndex.getEditStatus())) {
            return buildDropIndex(tableIndex);
        }
        if (EditStatusEnum.MODIFY.name().equals(tableIndex.getEditStatus())) {
            return StringUtils.join(buildDropIndex(tableIndex), ";\n", buildIndexScript(tableIndex));
        }
        if (EditStatusEnum.ADD.name().equals(tableIndex.getEditStatus())) {

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Populate TableIndexColumn.columnName for at least one column before building the index.
  2. Filter out blank-name columns earlier and skip index generation entirely when none remain.
  3. Validate the index model in the controller/service layer before reaching the DDL builder.

Example fix

// before
TableIndex idx = new TableIndex();
idx.setColumnList(List.of(new TableIndexColumn())); // name blank
DMIndexTypeEnum.XXX.buildIndexScript(idx);

// after
List<TableIndexColumn> named = idx.getColumnList().stream()
    .filter(c -> StringUtils.isNotBlank(c.getColumnName()))
    .toList();
if (named.isEmpty()) { /* skip or surface a user error */ }
idx.setColumnList(named);
DMIndexTypeEnum.XXX.buildIndexScript(idx);
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasNamedIndexColumn(TableIndex idx) {
    if (idx == null || idx.getColumnList() == null) return false;
    return idx.getColumnList().stream().anyMatch(c -> StringUtils.isNotBlank(c.getColumnName()));
}

Prevention

When it happens

Trigger: Calling DMIndexTypeEnum.buildIndexScript / buildModifyIndex on a TableIndex whose columnList is non-empty but every TableIndexColumn.getColumnName() is blank, or a list of placeholder rows.

Common situations: A UI 'add index' action that created column rows without binding names; importing an index whose column references were dropped; constructing a TableIndex programmatically and forgetting to populate columnName.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/5950cded63f5053d. Report an issue: GitHub.