{"record":{"id":"7fbe13bcbf65528d","repo":"quarkusio/quarkus","slug":"it-is-not-supported-to-connect-to-sql-server-versi","errorCode":null,"errorMessage":"It is not supported to connect to SQL Server versions older than 2012","messagePattern":"It is not supported to connect to SQL Server versions older than 2012","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/jdbc/jdbc-mssql/runtime/src/main/java/io/quarkus/jdbc/mssql/runtime/graal/com/microsoft/sqlserver/jdbc/SQLServerJDBCSubstitutions.java","lineNumber":77,"sourceCode":"\n@TargetClass(className = \"com.microsoft.sqlserver.jdbc.SQLServerLexer\")\n@Delete //Deleting this one explicitly, so to help with maintenance with the substitutions of SQLServerFMTQuery\nfinal class SQLServerLexerRemove {\n\n}\n\n/**\n * This will make sure the ANTLR4 Lexer included in the driver is not reachable; this was mostly\n * prevented by not allowing to explicitly set the useFmtOnly connection property, but this code\n * path would also get activated on very old SQL Server versions being detected on a connection.\n * Since that's not a constant that the compiler can rely on, we need one more substitution.\n */\n@TargetClass(className = \"com.microsoft.sqlserver.jdbc.SQLServerFMTQuery\")\nfinal class SQLServerFMTQuery {\n\n    @Substitute\n    SQLServerFMTQuery(String userSql) throws SQLServerException {\n        throw new IllegalStateException(\"It is not supported to connect to SQL Server versions older than 2012\");\n    }\n\n}\n\n/**\n * This substitution is not strictly necessary, but it helps by providing a better error message to our users.\n */\n@TargetClass(className = \"com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement\")\nfinal class DisableFMTRemove {\n\n    @Substitute\n    public final boolean getUseFmtOnly() throws SQLServerException {\n        return false;//Important for this to be disabled via a constant\n    }\n\n    @Substitute\n    public final void setUseFmtOnly(boolean useFmtOnly) throws SQLServerException {\n        if (useFmtOnly) {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/jdbc/jdbc-mssql/runtime/src/main/java/io/quarkus/jdbc/mssql/runtime/graal/com/microsoft/sqlserver/jdbc/SQLServerJDBCSubstitutions.java#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Upgrade the SQL Server instance to 2012 or newer (ideally a supported version)","Point the app at a newer server/instance and migrate the schema","If the old server cannot be upgraded, deploy the application in JVM mode","Place a newer SQL Server as a linked/forwarding target if direct upgrade is impossible"],"exampleFix":"// before\nString url = \"jdbc:sqlserver://legacyhost;database=db\"; // SQL Server 2008\n// after\nString url = \"jdbc:sqlserver://newhost2012plus;database=db\";","handlingStrategy":"validation","validationCode":"if (serverVersion < 2012) { throw new IllegalArgumentException(\"SQL Server versions older than 2012 are not supported in native mode\"); }","typeGuard":"static boolean isUnsupportedSqlServerVersion(int majorVersion) { return majorVersion < 11; } // 11 == SQL Server 2012","tryCatchPattern":"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; }","preventionTips":["Pin production SQL Server versions at 2012+","Check @@VERSION / driver-reported version before native deployments","Plan upgrades for legacy 2008 instances before native migration","Add a startup compatibility check of the DB version"],"tags":["native-image","jdbc","mssql","sql-server-2008","compatibility"],"backgroundTag":"native-image-unsupported-feature","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}