OtterMind/Chat2DB · error · IllegalArgumentException

Unsupported SUNDB index null ordering: {nullOrder}

Error message

Unsupported SUNDB index null ordering: {nullOrder}

What it means

Thrown by SUNDBSqlGuards.requireNullOrder when an index null-ordering value, upper-cased and trimmed, is non-empty and not one of NULLS FIRST, NULL FIRST, NULLS LAST, or NULL LAST. An empty value is allowed (returns ''), so this only fires for a non-empty unrecognized value.

Source

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

        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<>();
        List<String> topLevelWords = new ArrayList<>();
        boolean sawToken = false;
        boolean topLevelLiteralEnded = false;
        boolean intervalLiteralEnded = false;
        boolean readingIntervalQualifier = false;
        List<String> intervalQualifierWords = new ArrayList<>();

        for (int i = 0; i < expression.length(); i++) {
            char c = expression.charAt(i);
            if (Character.isWhitespace(c)) {
                continue;
            }
            sawToken = true;

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Use 'NULLS FIRST' or 'NULLS LAST' (NULL FIRST/NULL LAST are also accepted).
  2. Leave the value empty/null to omit null ordering entirely.
  3. Normalize FIRST->'NULLS FIRST' and LAST->'NULLS LAST' before building the index.

Example fix

// before
col.setNullOrder("FIRST");
// -> Unsupported SUNDB index null ordering

// after
col.setNullOrder("NULLS FIRST");
Defensive patterns

Strategy: validation

Validate before calling

Set<String> OK = Set.of("NULLS FIRST", "NULL FIRST", "NULLS LAST", "NULL LAST");
String n = StringUtils.trimToEmpty(nullOrder).toUpperCase(Locale.ROOT);
if (!n.isEmpty() && !OK.contains(n)) {
    throw new IllegalArgumentException("Reject SUNDB null ordering: " + nullOrder);
}

Type guard

static boolean isValidSundbNullOrder(String n) {
    if (n == null || n.isBlank()) return true;
    return Set.of("NULLS FIRST", "NULL FIRST", "NULLS LAST", "NULL LAST").contains(n.trim().toUpperCase(Locale.ROOT));
}

Prevention

When it happens

Trigger: Passing a non-empty null-ordering token other than the accepted spellings - e.g. 'FIRST', 'LAST', 'NULLS', or 'ASC'.

Common situations: UI/metadata supplying a partial value; cross-dialect import using plain FIRST/LAST; locale abbreviation.

Related errors


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