{"record":{"id":"4dad3a44358189cc","repo":"spring-projects/spring-ai","slug":"database-product-name-is-null-or-empty-defaulting","errorCode":null,"errorMessage":"Database product name is null or empty, defaulting to Postgres dialect.","messagePattern":"Database product name is null or empty, defaulting to Postgres dialect\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"memory-repositories/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryDialect.java","lineNumber":76,"sourceCode":"\t */\n\tdefault String getDeleteMessagesSql() {\n\t\treturn \"DELETE FROM SPRING_AI_CHAT_MEMORY WHERE conversation_id = ?\";\n\t}\n\n\t/**\n\t * Detects the dialect from the DataSource.\n\t */\n\tstatic JdbcChatMemoryRepositoryDialect from(DataSource dataSource) {\n\t\tString productName = null;\n\t\ttry {\n\t\t\tproductName = JdbcUtils.extractDatabaseMetaData(dataSource, DatabaseMetaData::getDatabaseProductName);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tlogger.warn(\"Due to failure in establishing JDBC connection or parsing metadata, the JDBC database vendor \"\n\t\t\t\t\t+ \"could not be determined\", e);\n\t\t}\n\t\tif (productName == null || productName.trim().isEmpty()) {\n\t\t\tlogger.warn(\"Database product name is null or empty, defaulting to Postgres dialect.\");\n\t\t\treturn new PostgresChatMemoryRepositoryDialect();\n\t\t}\n\t\treturn switch (productName) {\n\t\t\tcase \"PostgreSQL\" -> new PostgresChatMemoryRepositoryDialect();\n\t\t\tcase \"MySQL\", \"MariaDB\" -> new MysqlChatMemoryRepositoryDialect();\n\t\t\tcase \"Microsoft SQL Server\" -> new SqlServerChatMemoryRepositoryDialect();\n\t\t\tcase \"HSQL Database Engine\" -> new HsqldbChatMemoryRepositoryDialect();\n\t\t\tcase \"SQLite\" -> new SqliteChatMemoryRepositoryDialect();\n\t\t\tcase \"H2\" -> new H2ChatMemoryRepositoryDialect();\n\t\t\tcase \"Oracle\" -> new OracleChatMemoryRepositoryDialect();\n\t\t\tdefault -> // Add more as needed\n\t\t\t\tnew PostgresChatMemoryRepositoryDialect();\n\t\t};\n\t}\n\n}\n","sourceCodeStart":58,"sourceCodeEnd":93,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/memory-repositories/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepositoryDialect.java#L58-L93","documentation":"In JdbcChatMemoryRepositoryDialect.from(), when the extracted database product name is null or empty, the dialect resolution logs this warning and defaults to PostgresChatMemoryRepositoryDialect. Your repository will then generate PostgreSQL-flavored SQL regardless of the actual database, which can break queries on other vendors.","triggerScenarios":"from() called with a DataSource whose metadata returns a null/empty product name — connection issues swallowed earlier, drivers that do not implement the metadata call, or unusual/proxied datasources.","commonSituations":"Using a wrapper/proxy DataSource that doesn't delegate metadata; exotic or newer databases not in the known product-name list (PostgreSQL, MySQL/MariaDB, Microsoft SQL Server); misconfigured drivers; database down during startup with fallback continuing.","solutions":["Set the dialect explicitly on the builder so the Postgres default is never silently applied to a non-Postgres database","Inspect why product name is empty: test dataSource.getConnection().getMetaData().getDatabaseProductName() directly","If you use a proxy/wrapper DataSource, ensure it delegates getDatabaseProductName to the real connection","Check whether your database's product name string is supported; if not, implement JdbcChatMemoryRepositoryDialect for it"],"exampleFix":"// before\nJdbcChatMemoryRepository.builder().dataSource(unsupportedDbDataSource).build(); // defaults to Postgres\n\n// after\nJdbcChatMemoryRepository.builder()\n    .dataSource(unsupportedDbDataSource)\n    .dialect(new PostgresChatMemoryRepositoryDialect()) // explicit, intentional choice\n    .build();","handlingStrategy":"validation","validationCode":"try (Connection c = dataSource.getConnection()) {\n    String productName = c.getMetaData().getDatabaseProductName();\n    if (productName == null || productName.isBlank()) {\n        logger.warn(\"Product name unavailable; configure dialect explicitly to avoid Postgres default\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set an explicit dialect when using proxies or non-standard datasources","Test dataSource metadata extraction directly before blaming the repository","Confirm your database's product-name string is in the supported switch","Treat this warning as a red flag that Postgres SQL will run against a non-Postgres DB"],"tags":["jdbc","dialect","database-metadata","fallback"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}