{"record":{"id":"71402045d90ce22e","repo":"OtterMind/Chat2DB","slug":"unsupported-snowflake-column-type-columntype","errorCode":null,"errorMessage":"Unsupported Snowflake column type: {columnType}","messagePattern":"Unsupported Snowflake column type: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-plugins/chat2db-community-snowflake/src/main/java/ai/chat2db/plugin/snowflake/builder/SnowflakeSqlBuilder.java","lineNumber":199,"sourceCode":"        for (TableColumn tableColumn : newTable.getColumnList()) {\n            if (StringUtils.isNotBlank(tableColumn.getEditStatus()) && StringUtils.isNotBlank(tableColumn.getColumnType()) && StringUtils.isNotBlank(tableColumn.getName())) {\n                SnowflakeColumnTypeEnum typeEnum = requireColumnType(tableColumn.getColumnType());\n                script.append(SQLConstants.TAB).append(typeEnum.buildModifyColumn(tableColumn)).append(SQLConstants.COMMA_LINE_SEPARATOR);\n            }\n        }\n\n        if (script.length() > 2) {\n            script = new StringBuilder(script.substring(0, script.length() - 2));\n            script.append(SQLConstants.SEMICOLON);\n        }\n\n        return script.toString();\n    }\n\n    private SnowflakeColumnTypeEnum requireColumnType(String columnType) {\n        SnowflakeColumnTypeEnum typeEnum = SnowflakeColumnTypeEnum.getByType(columnType);\n        if (typeEnum == null) {\n            throw new IllegalArgumentException(\"Unsupported Snowflake column type: \" + columnType);\n        }\n        return typeEnum;\n    }\n\n    private SnowflakeIndexTypeEnum requireIndexType(String indexType) {\n        SnowflakeIndexTypeEnum typeEnum = SnowflakeIndexTypeEnum.getByType(indexType);\n        if (typeEnum == null) {\n            throw new IllegalArgumentException(\"Unsupported Snowflake index type: \" + indexType);\n        }\n        return typeEnum;\n    }\n\n}\n","sourceCodeStart":181,"sourceCodeEnd":213,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-plugins/chat2db-community-snowflake/src/main/java/ai/chat2db/plugin/snowflake/builder/SnowflakeSqlBuilder.java#L181-L213","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","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."],"exampleFix":"// before\ncolumn.setColumnType(\"TIMESTAMP_LTZ\"); // -> Unsupported Snowflake column type\nbuilder.buildAlterTable(oldTable, newTable);\n\n// after\ncolumn.setColumnType(\"TIMESTAMPLTZ\"); // matches enum registration\ncolumn.setColumnSize(9);\nbuilder.buildAlterTable(oldTable, newTable);","handlingStrategy":"validation","validationCode":"// Validate against the registered type names BEFORE calling buildAlterTable\nString baseName = column.getColumnType() == null ? null\n    : column.getColumnType().toUpperCase(Locale.ROOT).split(\"[(\")[0].trim();\nif (baseName == null || SnowflakeColumnTypeEnum.getByType(baseName) == null) {\n    // reject or normalize (e.g. TIMESTAMP_LTZ -> TIMESTAMPLTZ)\n    throw new IllegalArgumentException(\"Reject unsupported Snowflake type: \" + column.getColumnType());\n}","typeGuard":"// Narrow to a known Snowflake base type name before DDL generation\nstatic boolean isSupportedSnowflakeType(String raw) {\n    if (raw == null) return false;\n    String base = raw.toUpperCase(Locale.ROOT).split(\"[(]\")[0].trim();\n    return SnowflakeColumnTypeEnum.getByType(base) != null;\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["snowflake","ddl","column-type","alter-table"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}