OtterMind/Chat2DB · error · IllegalArgumentException

SQLite index must contain at least one named column

Error message

SQLite index must contain at least one named column

What it means

Thrown by SqliteIndexTypeEnum.buildIndexColumn when, after iterating tableIndex.getColumnList(), no entry had a non-blank columnName. The method builds the parenthesized column list by appending quoted names; if nothing was appended the buffer is still just '(', so it fails rather than emit malformed DDL.

Source

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

    private String buildIndexComment(TableIndex tableIndex) {
        if (StringUtils.isBlank(tableIndex.getComment())) {
            return "";
        } else {
            return StringUtils.join(SQL_COMMENT, tableIndex.getComment(), "'");
        }

    }

    private String buildIndexColumn(TableIndex tableIndex) {
        StringBuilder script = new StringBuilder();
        script.append("(");
        for (TableIndexColumn column : tableIndex.getColumnList()) {
            if (StringUtils.isNotBlank(column.getColumnName())) {
                script.append(quoteName(column.getColumnName())).append(",");
            }
        }
        if (script.length() == 1) {
            throw new IllegalArgumentException("SQLite index must contain at least one named column");
        }
        script.deleteCharAt(script.length() - 1);
        script.append(")");
        return script.toString();
    }

    private String buildIndexName(TableIndex tableIndex) {
        if (this.equals(PRIMARY_KEY)) {
            return quoteName(tableIndex.getTableName() + "_pk");
        } else {
            return quoteName(tableIndex.getName());
        }
    }

    private static String quoteName(String name) {
        return SqliteIdentifierProcessor.INSTANCE.quoteIdentifierAlways(name);
    }

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Populate columnList with at least one TableIndexColumn carrying a non-blank columnName.
  2. Reject/validate empty index columns at the API boundary before DDL generation.
  3. Skip the index entirely when no columns are configured.

Example fix

// before
index.setColumnList(Collections.emptyList());
// -> SQLite index must contain at least one named column

// after
TableIndexColumn c = new TableIndexColumn();
c.setColumnName("rowid");
index.setColumnList(List.of(c));
Defensive patterns

Strategy: validation

Validate before calling

boolean hasNamed = tableIndex.getColumnList() != null
    && tableIndex.getColumnList().stream()
        .anyMatch(c -> StringUtils.isNotBlank(c.getColumnName()));
if (!hasNamed) {
    throw new IllegalArgumentException("SQLite index needs a named column");
}

Type guard

static boolean sqliteIndexHasNamedColumn(TableIndex idx) {
    return idx.getColumnList() != null && idx.getColumnList().stream()
        .anyMatch(c -> StringUtils.isNotBlank(c.getColumnName()));
}

Prevention

When it happens

Trigger: Building an index whose columnList is empty, or whose every column has a null/blank getColumnName().

Common situations: An index created in the UI before columns are chosen; metadata that lists an index without resolved column names; partial-column model serialization.

Related errors


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