alibaba/nacos · error · SQLException

Unsupported SQL: %s. Nacos only support DML and some DDL SQL

Error message

Unsupported SQL: %s. Nacos only support DML and some DDL SQL.

What it means

Thrown by SqlTypeLimiter.throwException (private) as a SQLException when an SQL statement's first token is not an allowed DML verb (INSERT/UPDATE/DELETE/SELECT) nor an allowed DDL verb (CREATE/ALTER), or when CREATE/ALTER is followed by a second token not in {SCHEMA, TABLE, INDEX}. The limiter guards embedded Derby SQL execution and is enabled by default (nacos.persistence.sql.derby.limit.enabled=true).

Source

Thrown at persistence/src/main/java/com/alibaba/nacos/persistence/repository/embedded/sql/limiter/SqlTypeLimiter.java:133

        }
        if (!allowedDdlSqls.contains(firstToken)) {
            throwException(trimmedSql);
        }
        checkSqlForSecondToken(firstTokenIndex, trimmedSql);
    }
    
    @Override
    public void doLimit(List<String> sql) throws SQLException {
        if (null == sql || !enabledLimit) {
            return;
        }
        for (String each : sql) {
            doLimit(each);
        }
    }
    
    private void throwException(String sql) throws SQLException {
        throw new SQLException(
            String.format("Unsupported SQL: %s. Nacos only support DML and some DDL SQL.", sql));
    }
    
    private void checkSqlForSecondToken(int firstTokenIndex, String trimmedSql)
        throws SQLException {
        int secondTokenIndex = trimmedSql.indexOf(" ", firstTokenIndex + 1);
        if (-1 == secondTokenIndex) {
            secondTokenIndex = trimmedSql.length();
        }
        String secondToken =
            trimmedSql.substring(firstTokenIndex + 1, secondTokenIndex).toUpperCase();
        if (!allowedDdlScopes.contains(secondToken)) {
            throwException(trimmedSql);
        }
    }
}

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Restrict SQL to INSERT/UPDATE/DELETE/SELECT, or CREATE SCHEMA/TABLE/INDEX, or ALTER TABLE.
  2. If you legitimately need a disallowed statement, re-evaluate: the limiter is a safety control for embedded Derby, not a toggle for arbitrary DDL.
  3. To disable the limiter for a controlled maintenance operation set nacos.persistence.sql.derby.limit.enabled=false (do this only in a trusted, isolated maintenance window).

Example fix

// before: DROP is not allowed by the limiter
doLimit("DROP TABLE config_info");

// after: use the supported DDL scope, or disable limiter for trusted maintenance
// only if strictly necessary
// System.setProperty("nacos.persistence.sql.derby.limit.enabled", "false");
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<String> OK_VERBS = Set.of(
    "INSERT","UPDATE","DELETE","SELECT","CREATE","ALTER");
private static final Set<String> OK_DDL_SCOPE = Set.of("SCHEMA","TABLE","INDEX");
static boolean isAllowedByLimiter(String sql) {
    String t = sql.trim().toUpperCase();
    String first = t.contains(" ") ? t.substring(0, t.indexOf(' ')) : t;
    if (!OK_VERBS.contains(first)) return false;
    if (Set.of("CREATE","ALTER").contains(first)) {
        int s = t.indexOf(' '), e = t.indexOf(' ', s + 1);
        String second = t.substring(s + 1, e < 0 ? t.length() : e);
        return OK_DDL_SCOPE.contains(second);
    }
    return true;
}

Type guard

static boolean isAllowedByLimiter(String sql) { /* see validationCode */ return false; }

Try / catch

try {
    databaseOperate.update(sqlCtx);
} catch (SQLException e) {
    if (e.getMessage().startsWith("Unsupported SQL:")) {
        // rejected by SqlTypeLimiter; do not retry with the same SQL
        throw new IllegalStateException("blocked SQL", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Executing SQL against the embedded Derby store whose leading verb is disallowed (e.g. DROP, TRUNCATE, GRANT), or a CREATE/ALTER whose target is not SCHEMA/TABLE/INDEX (e.g. CREATE VIEW). Reached via ModifyRequest/SelectRequest SQL passed to databaseOperate.

Common situations: Custom plugins or maintenance code issuing raw SQL to the embedded store; migrations that use DROP or DCL; trying to run a CREATE PROCEDURE or CREATE VIEW which the limiter rejects.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/7d966ee9cb0f56e4. Report an issue: GitHub.