{"record":{"id":"341b584e493cb338","repo":"spring-projects/spring-ai","slug":"datasource-must-be-set-either-via-datasource-or","errorCode":null,"errorMessage":"DataSource must be set (either via dataSource() or jdbcTemplate())","messagePattern":"DataSource must be set \\(either via dataSource\\(\\) or jdbcTemplate\\(\\)\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"memory-repositories/spring-ai-model-chat-memory-repository-jdbc/src/main/java/org/springframework/ai/chat/memory/repository/jdbc/JdbcChatMemoryRepository.java","lineNumber":238,"sourceCode":"\t\t\tthis.platformTransactionManager = txManager;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic JdbcChatMemoryRepository build() {\n\t\t\tDataSource effectiveDataSource = resolveDataSource();\n\t\t\tJdbcChatMemoryRepositoryDialect effectiveDialect = resolveDialect(effectiveDataSource);\n\t\t\treturn new JdbcChatMemoryRepository(resolveJdbcTemplate(), effectiveDialect,\n\t\t\t\t\tthis.platformTransactionManager);\n\t\t}\n\n\t\tprivate JdbcTemplate resolveJdbcTemplate() {\n\t\t\tif (this.jdbcTemplate != null) {\n\t\t\t\treturn this.jdbcTemplate;\n\t\t\t}\n\t\t\tif (this.dataSource != null) {\n\t\t\t\treturn new JdbcTemplate(this.dataSource);\n\t\t\t}\n\t\t\tthrow new IllegalArgumentException(\"DataSource must be set (either via dataSource() or jdbcTemplate())\");\n\t\t}\n\n\t\tprivate DataSource resolveDataSource() {\n\t\t\tif (this.dataSource != null) {\n\t\t\t\treturn this.dataSource;\n\t\t\t}\n\t\t\tif (this.jdbcTemplate != null && this.jdbcTemplate.getDataSource() != null) {\n\t\t\t\treturn this.jdbcTemplate.getDataSource();\n\t\t\t}\n\t\t\tthrow new IllegalArgumentException(\"DataSource must be set (either via dataSource() or jdbcTemplate())\");\n\t\t}\n\n\t\tprivate JdbcChatMemoryRepositoryDialect resolveDialect(DataSource dataSource) {\n\t\t\tif (this.dialect == null) {\n\t\t\t\treturn JdbcChatMemoryRepositoryDialect.from(dataSource);\n\t\t\t}\n\t\t\telse {\n\t\t\t\twarnIfDialectMismatch(dataSource, this.dialect);","sourceCodeStart":220,"sourceCodeEnd":256,"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/JdbcChatMemoryRepository.java#L220-L256","documentation":"JdbcChatMemoryRepository.Builder.build() resolves the JdbcTemplate used by the repository. If neither jdbcTemplate() nor dataSource() was supplied on the builder, resolveJdbcTemplate() throws IllegalArgumentException. The repository cannot execute any SQL without one of these.","triggerScenarios":"Calling JdbcChatMemoryRepository.builder().build() (or via JdbcChatMemoryConfig) without calling either .dataSource(ds) or .jdbcTemplate(jt) first.","commonSituations":"Forgot to wire the DataSource bean into the builder; copied a config example and removed the dataSource() line; building the repository manually in tests instead of via Spring auto-configuration.","solutions":["Call .dataSource(...) on the builder with your DataSource bean","Or call .jdbcTemplate(...) with an existing JdbcTemplate bean","If using Spring Boot, verify a DataSource bean exists and is injectable (starter-jdbc or starter-data-jpa on classpath)","Check auto-configuration ordering so the repository bean is created after the DataSource"],"exampleFix":"// before\nJdbcChatMemoryRepository repo = JdbcChatMemoryRepository.builder().build();\n// after\nJdbcChatMemoryRepository repo = JdbcChatMemoryRepository.builder()\n    .dataSource(dataSource)\n    .build();","handlingStrategy":"validation","validationCode":"if (dataSource == null && jdbcTemplate == null) {\n    throw new IllegalStateException(\"Configure dataSource() or jdbcTemplate() before build()\");\n}","typeGuard":null,"tryCatchPattern":"try { repo = JdbcChatMemoryRepository.builder().build(); }\ncatch (IllegalArgumentException e) { repo = JdbcChatMemoryRepository.builder().dataSource(defaultDs).build(); }","preventionTips":["Always set .dataSource(...) or .jdbcTemplate(...) immediately on the builder","Prefer Spring Boot auto-configuration over manual construction","Add a startup smoke test that builds the repository bean"],"tags":["jdbc","builder","datasource","illegal-argument","configuration"],"backgroundTag":"missing-required-config-field","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}