OtterMind/Chat2DB · error · IllegalArgumentException
Invalid SQL Server collation name: {collation}
Error message
Invalid SQL Server collation name: {collation} What it means
Thrown by SqlServerSqlGuards.validateCollation when the collation is null or does not fully match the allow-list [A-Za-z0-9_]+. Collation names are embedded as bare (unquoted) tokens in generated DDL, so anything outside ASCII alphanumerics/underscore is rejected to block DDL injection (fail closed).
Source
Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-sqlserver/src/main/java/ai/chat2db/plugin/sqlserver/SqlServerSqlGuards.java:49
"NATIONAL CHAR",
"NATIONAL CHAR VARYING",
"NATIONAL CHARACTER",
"NATIONAL CHARACTER VARYING");
private static final Set<String> COLUMN_CLAUSE_KEYWORDS = Set.of(
"CHECK", "CONSTRAINT", "DEFAULT", "ENCRYPTED", "IDENTITY", "MASKED",
"PERSISTED", "REFERENCES", "ROWGUIDCOL", "SPARSE", "UNIQUE");
private SqlServerSqlGuards() {
}
/**
* Validates a collation name before it is embedded into generated DDL.
* Returns the collation unchanged when it matches the allow-list; throws
* otherwise (fail closed).
*/
public static String validateCollation(String collation) {
if (collation == null || !COLLATION_NAME_PATTERN.matcher(collation).matches()) {
throw new IllegalArgumentException("Invalid SQL Server collation name: " + collation);
}
return collation;
}
/**
* Accepts a SQL Server built-in or schema-qualified user-defined type,
* with an optional balanced argument list such as {@code decimal(18, 2)},
* {@code nvarchar(max)}, or {@code xml(CONTENT [dbo].[Collection])}.
*/
public static String requireColumnTypeExpression(String columnType) {
if (StringUtils.isBlank(columnType)) {
throw invalid("column type", columnType);
}
String expression = columnType.trim();
int argumentsStart = findArgumentsStart(expression);
String typeName = argumentsStart < 0 ? expression : expression.substring(0, argumentsStart).trim();
if (!isTypeName(typeName)) {
throw invalid("column type", columnType);View on GitHub (pinned to 5ee1e990e7)
Solutions
- Supply only ASCII letters, digits, and underscore (e.g. SQL_Latin1_General_CP1_CI_AS).
- Pre-validate the collation against [A-Za-z0-9_]+ before setting it on the column model.
- If null/empty collation is intended, omit the COLLATE clause instead of passing null.
Example fix
// before
column.setCollationName("Latin1_General CI AS"); // spaces
// -> Invalid SQL Server collation name
// after
column.setCollationName("Latin1_General_CI_AS"); Defensive patterns
Strategy: validation
Validate before calling
private static final java.util.regex.Pattern COLL = java.util.regex.Pattern.compile("[A-Za-z0-9_]+");
if (collation != null && !COLL.matcher(collation).matches()) {
throw new IllegalArgumentException("Reject collation: " + collation);
} Type guard
static boolean isSafeSqlServerCollation(String c) {
return c != null && c.matches("[A-Za-z0-9_]+");
} Prevention
- Restrict collations to ASCII alphanumerics/underscore.
- Omit the COLLATE clause for null/empty rather than forwarding null.
- Validate at the boundary with the same regex.
When it happens
Trigger: Passing a collation containing a space, dot, hyphen, parentheses, quote, or any non-[A-Za-z0-9_] character - e.g. 'Latin1_General_CI_AS' is valid, but 'Latin1 General' or a Windows collation with a locale suffix delimiter is not. A null collation also triggers it.
Common situations: User-supplied or JDBC-reported collation with unexpected punctuation; copy-paste introducing whitespace; an attempt to pass a collation ID rather than its name.
Related errors
- Unsafe {what} name: {name}
- Source table DDL is empty
- Invalid SQL Server view attribute: {viewAttribute}
- Invalid SQL Server index column sort order: {ascOrDesc}
- Invalid SUNDB index sort direction: {value}
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/24da10f9b28db0dc.
Report an issue: GitHub.