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
- 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.
- If using a TIMESTAMP_LTZ/NTZ/TZ family, use the no-underscore forms: TIMESTAMPLTZ, TIMESTAMPNTZ, TIMESTAMPTZ.
- Confirm the exact supported set in SnowflakeColumnTypeEnum (lines 21-52) and map/normalize your input before calling buildAlterTable.
- 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
- Store only the bare base type name in TableColumn.columnType; carry size/precision in columnSize/decimalDigits.
- Normalize TIMESTAMP_LTZ/NTZ/TZ family names to TIMESTAMPLTZ/TIMESTAMPNTZ/TIMESTAMPTZ before reaching the builder.
- Validate type names at the API/UI boundary using SnowflakeColumnTypeEnum.getByType.
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
- Invalid MySQL column type: {value}
- Invalid Snowflake {what}: {value}
- Invalid Snowflake index sort direction: {value}
- Unsupported Snowflake index type: {indexType}
- Snowflake index requires at least one named column
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/71402045d90ce22e.
Report an issue: GitHub.