OtterMind/Chat2DB · error · IllegalArgumentException

Unsupported SUNDB constraint type: {constraintType}

Error message

Unsupported SUNDB constraint type: {constraintType}

What it means

Thrown by SUNDBSqlGuards.requireConstraintType when a constraint type, upper-cased and trimmed, is not in {CHECK, FOREIGN KEY, PRIMARY KEY, UNIQUE}. The validator whitelists only these constraint kinds before emitting DDL.

Source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-sundb/src/main/java/ai/chat2db/plugin/sundb/SUNDBSqlGuards.java:104

     * rejected to block DDL injection.
     */
    public static String requireUnit(String unit) {
        String trimmed = StringUtils.trimToEmpty(unit);
        if ("CHAR".equalsIgnoreCase(trimmed)) {
            return "CHAR";
        }
        if ("BYTE".equalsIgnoreCase(trimmed)) {
            return "BYTE";
        }
        throw new IllegalArgumentException("Unsupported VARCHAR unit: " + unit);
    }

    public static String requireConstraintType(String constraintType) {
        String normalized = StringUtils.trimToEmpty(constraintType).toUpperCase(Locale.ROOT);
        if (CONSTRAINT_TYPES.contains(normalized)) {
            return normalized;
        }
        throw new IllegalArgumentException("Unsupported SUNDB constraint type: " + constraintType);
    }

    public static String requireNullOrder(String nullOrder) {
        String normalized = StringUtils.trimToEmpty(nullOrder).toUpperCase(Locale.ROOT);
        if (normalized.isEmpty()) {
            return "";
        }
        if ("NULLS FIRST".equals(normalized) || "NULL FIRST".equals(normalized)) {
            return "NULLS FIRST";
        }
        if ("NULLS LAST".equals(normalized) || "NULL LAST".equals(normalized)) {
            return "NULLS LAST";
        }
        throw new IllegalArgumentException("Unsupported SUNDB index null ordering: " + nullOrder);
    }

    private static void scanExpression(String expression, boolean typeExpression, String description) {
        Deque<Character> parentheses = new ArrayDeque<>();

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Use one of CHECK, FOREIGN KEY, PRIMARY KEY, or UNIQUE (case-insensitive).
  2. Handle NOT NULL / DEFAULT as column attributes, not as constraint types.
  3. Normalize/validate the constraint type against the allowed set before DDL generation.

Example fix

// before
constraint.setType("NOT NULL");
// -> Unsupported SUNDB constraint type

// after
constraint.setType("CHECK");
Defensive patterns

Strategy: validation

Validate before calling

Set<String> OK = Set.of("CHECK", "FOREIGN KEY", "PRIMARY KEY", "UNIQUE");
if (!OK.contains(StringUtils.trimToEmpty(constraintType).toUpperCase(Locale.ROOT))) {
    throw new IllegalArgumentException("Reject SUNDB constraint type: " + constraintType);
}

Type guard

static boolean isValidSundbConstraintType(String t) {
    return t != null && Set.of("CHECK", "FOREIGN KEY", "PRIMARY KEY", "UNIQUE")
        .contains(t.trim().toUpperCase(Locale.ROOT));
}

Prevention

When it happens

Trigger: Passing a constraint type string outside the allowed set - e.g. 'NOT NULL', 'DEFAULT', 'INDEX', or a free-text label.

Common situations: Confusing column-level NOT NULL/DEFAULT (not constraint types here) with table-level constraint kinds; cross-dialect metadata naming differences; UI label passed instead of the canonical value.

Related errors


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