quarkusio/quarkus · error · IllegalStateException

It is not supported to connect to SQL Server versions older

Error message

It is not supported to connect to SQL Server versions older than 2012

What it means

The MSSQL driver's FMT-only parsing machinery (used for old SQL Server versions) is substituted in native mode to throw. Quarkus only supports connecting to SQL Server 2012+, where parameter metadata can be obtained via sp_describe_undeclared_parameters; connecting to pre-2012 servers would need the removed code path, so it fails fast with this message.

Source

Thrown at extensions/jdbc/jdbc-mssql/runtime/src/main/java/io/quarkus/jdbc/mssql/runtime/graal/com/microsoft/sqlserver/jdbc/SQLServerJDBCSubstitutions.java:77

@TargetClass(className = "com.microsoft.sqlserver.jdbc.SQLServerLexer")
@Delete //Deleting this one explicitly, so to help with maintenance with the substitutions of SQLServerFMTQuery
final class SQLServerLexerRemove {

}

/**
 * This will make sure the ANTLR4 Lexer included in the driver is not reachable; this was mostly
 * prevented by not allowing to explicitly set the useFmtOnly connection property, but this code
 * path would also get activated on very old SQL Server versions being detected on a connection.
 * Since that's not a constant that the compiler can rely on, we need one more substitution.
 */
@TargetClass(className = "com.microsoft.sqlserver.jdbc.SQLServerFMTQuery")
final class SQLServerFMTQuery {

    @Substitute
    SQLServerFMTQuery(String userSql) throws SQLServerException {
        throw new IllegalStateException("It is not supported to connect to SQL Server versions older than 2012");
    }

}

/**
 * This substitution is not strictly necessary, but it helps by providing a better error message to our users.
 */
@TargetClass(className = "com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement")
final class DisableFMTRemove {

    @Substitute
    public final boolean getUseFmtOnly() throws SQLServerException {
        return false;//Important for this to be disabled via a constant
    }

    @Substitute
    public final void setUseFmtOnly(boolean useFmtOnly) throws SQLServerException {
        if (useFmtOnly) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Upgrade the SQL Server instance to 2012 or newer (ideally a supported version)
  2. Point the app at a newer server/instance and migrate the schema
  3. If the old server cannot be upgraded, deploy the application in JVM mode
  4. Place a newer SQL Server as a linked/forwarding target if direct upgrade is impossible

Example fix

// before
String url = "jdbc:sqlserver://legacyhost;database=db"; // SQL Server 2008
// after
String url = "jdbc:sqlserver://newhost2012plus;database=db";
Defensive patterns

Strategy: validation

Validate before calling

if (serverVersion < 2012) { throw new IllegalArgumentException("SQL Server versions older than 2012 are not supported in native mode"); }

Type guard

static boolean isUnsupportedSqlServerVersion(int majorVersion) { return majorVersion < 11; } // 11 == SQL Server 2012

Try / catch

try { conn = ds.getConnection(); } catch (IllegalStateException e) { if (e.getMessage().contains("older than 2012")) { log.error("Upgrade SQL Server to 2012+ or run in JVM mode"); } throw e; }

Prevention

When it happens

Trigger: Native-mode connection to SQL Server 2008/2008 R2 or older (including old on-prem instances), when the substituted SQLServerFMTQuery constructor is invoked during query preparation/metadata handling.

Common situations: Legacy on-prem SQL Server 2008 instances still in production; old SQL Server Express boxes; Azure environments being consolidated onto native deployments while old servers remain.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/7fbe13bcbf65528d. Report an issue: GitHub.