OtterMind/Chat2DB · error · IllegalArgumentException

Unsupported Snowflake column type: {columnType}

Error message

Unsupported Snowflake column type: {columnType}

What it means

Thrown by SnowflakeSqlBuilder.requireColumnType during ALTER TABLE generation when a column's type string has no entry in SnowflakeColumnTypeEnum. The lookup upper-cases the input and matches it against the enum's registered type names (NUMBER, VARCHAR, TIMESTAMP, TIMESTAMPLTZ, TIMESTAMPNTZ, TIMESTAMPTZ, VARIANT, OBJECT, ARRAY, GEOGRAPHY, etc.). Note the CREATE path (SnowflakeColumnTypeEnum.buildCreateColumnSql) tolerates unknown types via a fallback, but the ALTER path here does not - it fails hard.

Source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-snowflake/src/main/java/ai/chat2db/plugin/snowflake/builder/SnowflakeSqlBuilder.java:199

        for (TableColumn tableColumn : newTable.getColumnList()) {
            if (StringUtils.isNotBlank(tableColumn.getEditStatus()) && StringUtils.isNotBlank(tableColumn.getColumnType()) && StringUtils.isNotBlank(tableColumn.getName())) {
                SnowflakeColumnTypeEnum typeEnum = requireColumnType(tableColumn.getColumnType());
                script.append(SQLConstants.TAB).append(typeEnum.buildModifyColumn(tableColumn)).append(SQLConstants.COMMA_LINE_SEPARATOR);
            }
        }

        if (script.length() > 2) {
            script = new StringBuilder(script.substring(0, script.length() - 2));
            script.append(SQLConstants.SEMICOLON);
        }

        return script.toString();
    }

    private SnowflakeColumnTypeEnum requireColumnType(String columnType) {
        SnowflakeColumnTypeEnum typeEnum = SnowflakeColumnTypeEnum.getByType(columnType);
        if (typeEnum == null) {
            throw new IllegalArgumentException("Unsupported Snowflake column type: " + columnType);
        }
        return typeEnum;
    }

    private SnowflakeIndexTypeEnum requireIndexType(String indexType) {
        SnowflakeIndexTypeEnum typeEnum = SnowflakeIndexTypeEnum.getByType(indexType);
        if (typeEnum == null) {
            throw new IllegalArgumentException("Unsupported Snowflake index type: " + indexType);
        }
        return typeEnum;
    }

}

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Pass the bare base type name only (e.g. 'VARCHAR', 'NUMBER', 'TIMESTAMPLTZ'), not a parameterized form; size/precision are carried separately in TableColumn.columnSize/decimalDigits.
  2. If using a TIMESTAMP_LTZ/NTZ/TZ family, use the no-underscore forms: TIMESTAMPLTZ, TIMESTAMPNTZ, TIMESTAMPTZ.
  3. Confirm the exact supported set in SnowflakeColumnTypeEnum (lines 21-52) and map/normalize your input before calling buildAlterTable.
  4. For genuinely unsupported types, use the CREATE TABLE path (which has a validated fallback) instead of the ALTER path, or add the type to the enum with an explicit column builder.

Example fix

// before
column.setColumnType("TIMESTAMP_LTZ"); // -> Unsupported Snowflake column type
builder.buildAlterTable(oldTable, newTable);

// after
column.setColumnType("TIMESTAMPLTZ"); // matches enum registration
column.setColumnSize(9);
builder.buildAlterTable(oldTable, newTable);
Defensive patterns

Strategy: validation

Validate before calling

// Validate against the registered type names BEFORE calling buildAlterTable
String baseName = column.getColumnType() == null ? null
    : column.getColumnType().toUpperCase(Locale.ROOT).split("[(")[0].trim();
if (baseName == null || SnowflakeColumnTypeEnum.getByType(baseName) == null) {
    // reject or normalize (e.g. TIMESTAMP_LTZ -> TIMESTAMPLTZ)
    throw new IllegalArgumentException("Reject unsupported Snowflake type: " + column.getColumnType());
}

Type guard

// Narrow to a known Snowflake base type name before DDL generation
static boolean isSupportedSnowflakeType(String raw) {
    if (raw == null) return false;
    String base = raw.toUpperCase(Locale.ROOT).split("[(]")[0].trim();
    return SnowflakeColumnTypeEnum.getByType(base) != null;
}

Prevention

When it happens

Trigger: Calling buildAlterTable with a TableColumn whose columnType is non-blank but not equal (case-insensitive) to any enum type name. Common mismatches: passing 'TIMESTAMP_LTZ'/'TIMESTAMP_NTZ'/'TIMESTAMP_TZ' (the enum registers them as 'TIMESTAMPLTZ'/'TIMESTAMPNTZ'/'TIMESTAMPTZ' with no underscore), or a parameterized raw string like 'VARCHAR(255)' or 'NUMBER(10,2)' instead of the bare base name 'VARCHAR'/'NUMBER'.

Common situations: Reverse-engineering metadata that reports type names with underscores (TIMESTAMP_LTZ); UI/code passing a fully-qualified or parameterized type string into the column model; upgrading the plugin and encountering a newer Snowflake type (e.g. a GEOGRAPHY variant) not yet in the enum.

Related errors


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