OtterMind/Chat2DB · error · IllegalArgumentException

Invalid MySQL index sort direction: {value}

Error message

Invalid MySQL index sort direction: {value}

What it means

Thrown by MysqlSqlGuards.requireAscOrDesc when an index column sort direction is not ASC or DESC (matched case-insensitively after trim). Only those two directions are legal MySQL index sort keywords; the function returns the canonical uppercase form. Null, empty, or any other value is rejected.

Source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-mysql/src/main/java/ai/chat2db/plugin/mysql/MysqlSqlGuards.java:119

        String trimmed = StringUtils.trimToEmpty(value);
        if (!COLUMN_TYPE_PATTERN.matcher(trimmed).matches()) {
            throw new IllegalArgumentException("Invalid MySQL column type: " + value);
        }
        return trimmed;
    }

    /**
     * Validate an index sort direction: only ASC/DESC are legal, returned in canonical uppercase.
     */
    public static String requireAscOrDesc(String value) {
        String trimmed = StringUtils.trimToEmpty(value);
        if ("ASC".equalsIgnoreCase(trimmed)) {
            return "ASC";
        }
        if ("DESC".equalsIgnoreCase(trimmed)) {
            return "DESC";
        }
        throw new IllegalArgumentException("Invalid MySQL index sort direction: " + value);
    }

    /**
     * Validate an option that must be one of the given enum constants (e.g. view algorithm /
     * sql security / check option). Returns the canonical enum name.
     */
    public static <E extends Enum<E>> String requireEnumConstant(String value, E[] constants, String what) {
        for (E constant : constants) {
            if (constant.name().equalsIgnoreCase(StringUtils.trimToEmpty(value))) {
                return constant.name();
            }
        }
        throw new IllegalArgumentException("Invalid MySQL " + what + ": " + value);
    }

    /**
     * Parse and re-escape a comma-separated ENUM/SET value list. Quoted values are decoded before
     * they are escaped again, so metadata such as {@code 'can''t'} is not double-escaped. A

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Only pass ASC or DESC to requireAscOrDesc; for columns without a direction, omit the call entirely.
  2. If a null/empty direction means 'no sort', skip validation and do not emit a direction clause.
  3. Map UI direction values to ASC/DESC/null at the boundary and branch on null.
  4. Trim and upper-case the input before comparison.

Example fix

// before
MysqlSqlGuards.requireAscOrDesc(direction);

// after
String d = StringUtils.trimToNull(direction);
String sortDir = d == null ? null : d.toUpperCase(Locale.ROOT);
if (sortDir != null && !"ASC".equals(sortDir) && !"DESC".equals(sortDir)) {
    throw new IllegalArgumentException("Invalid MySQL index sort direction: " + direction);
}
// only guard when a direction is actually required:
if (sortDir != null) {
    MysqlSqlGuards.requireAscOrDesc(sortDir);
}
Defensive patterns

Strategy: validation

Validate before calling

String d = StringUtils.trimToNull(direction);
if (d != null) {
    String up = d.toUpperCase(Locale.ROOT);
    if (!"ASC".equals(up) && !"DESC".equals(up)) {
        throw new IllegalArgumentException("Invalid MySQL index sort direction: " + direction);
    }
    MysqlSqlGuards.requireAscOrDesc(up);
}

Type guard

static boolean isAscOrDesc(String value) {
    String d = StringUtils.trimToEmpty(value).toUpperCase(Locale.ROOT);
    return "ASC".equals(d) || "DESC".equals(d);
}

Prevention

When it happens

Trigger: Calling requireAscOrDesc(value) with null, an empty string, 'NONE', 'ASCENDING', or any token other than ASC/DESC.

Common situations: A UI index builder defaulting direction to null/'NONE' for non-sorted columns; the value not set when the user leaves the direction dropdown empty; an API payload forwarding an unrecognised direction string.

Related errors


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