spring-projects / spring-projects/spring-ai

RedisChatMemoryRepository auto-config backs off when any ChatMemory bean exists (ChatMemory.class in ConditionalOnMissingBean)

Open Beginner friendly
#6,926 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage
Dominant language
Java
Stars
9.5k
Forks
2.9k
Avg merge
1d 7h
Merged PRs (30d)
6

Description

Bug description

RedisChatMemoryRepositoryAutoConfiguration refuses to register RedisChatMemoryRepository when any ChatMemory bean is already present:

@Bean
@ConditionalOnMissingBean({ RedisChatMemoryRepository.class, ChatMemory.class, ChatMemoryRepository.class })
public RedisChatMemoryRepository redisChatMemoryRepository(...) { ... }

That condition is too broad for a repository auto-configuration.

Spring AI separates responsibilities clearly:

  • ChatMemoryRepository – persistence
  • ChatMemory – retention strategy (e.g. MessageWindowChatMemory with maxMessages)

The docs encourage adding the Redis starter for auto-configured RedisChatMemoryRepository, and then customizing ChatMemory on top of that repository. Including ChatMemory.class in @ConditionalOnMissingBean breaks that pattern: defining a custom ChatMemory suppresses Redis repository auto-config entirely.

Even without a custom bean, ChatMemoryAutoConfiguration always provides a default ChatMemory, so any scenario where that bean is visible before Redis auto-config evaluates will also suppress RedisChatMemoryRepository.

Comparison with sibling store auto-configs

JdbcChatMemoryRepositoryAutoConfiguration and CassandraChatMemoryRepositoryAutoConfiguration only use @ConditionalOnMissingBean on the repository type itself — they do not back off because a ChatMemory exists. Redis should follow the same pattern.

Relation to #5623 / #5644 (please do not close as duplicate without checking main)

This is related to https://github.com/spring-projects/spring-ai/issues/5623, but it is not fully resolved on current main.

PR https://github.com/spring-projects/spring-ai/pull/5644 explicitly fixed the same root cause for the older RedisChatMemoryAutoConfiguration by:

  1. ordering Redis auto-config before ChatMemoryAutoConfiguration
  2. narrowing the missing-bean condition to ChatMemoryRepository only (removing ChatMemory.class)

Relevant change from that PR:

- @ConditionalOnMissingBean({ RedisChatMemoryRepository.class, ChatMemory.class, ChatMemoryRepository.class })
+ @ConditionalOnMissingBean(ChatMemoryRepository.class)

However, on current main, the successor module RedisChatMemoryRepositoryAutoConfiguration still has:

@ConditionalOnMissingBean({ RedisChatMemoryRepository.class, ChatMemory.class, ChatMemoryRepository.class })

Source (main):
https://github.com/spring-projects/spring-ai/blob/main/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-redis/src/main/java/org/springframework/ai/model/chat/memory/repository/redis/autoconfigure/RedisChatMemoryRepositoryAutoConfiguration.java

So the before = ChatMemoryAutoConfiguration.class ordering helps the default InMemory vs Redis race, but ChatMemory.class being part of the condition remains a regression / incomplete fix relative to what #5644 proposed.

Environment

  • Spring AI main (verified against current RedisChatMemoryRepositoryAutoConfiguration)
  • spring-ai-starter-model-chat-memory-repository-redis

Steps to reproduce

  1. Add spring-ai-starter-model-chat-memory-repository-redis.
  2. Declare a custom ChatMemory that depends on the auto-configured Redis repository, e.g.:
@Bean
public ChatMemory chatMemory(RedisChatMemoryRepository redisChatMemoryRepository) {
    return MessageWindowChatMemory.builder()
            .chatMemoryRepository(redisChatMemoryRepository)
            .maxMessages(20)
            .build();
}
  1. Start the application.

Expected behavior

  • RedisChatMemoryRepository is auto-configured when no ChatMemoryRepository (or Redis-specific repository) bean exists.
  • A user-defined ChatMemory must not prevent Redis repository auto-configuration.
  • Align Redis with JDBC/Cassandra: repository auto-config should not condition on ChatMemory.class.

Actual behavior

Because a ChatMemory bean is present, RedisChatMemoryRepository is not registered. The custom ChatMemory bean then fails to obtain RedisChatMemoryRepository, or the app falls back to in-memory storage depending on ordering / other beans.

Suggested fix

Narrow the condition back to repository types only, as in #5644, for example:

@ConditionalOnMissingBean(ChatMemoryRepository.class)
// or at most:
@ConditionalOnMissingBean({ RedisChatMemoryRepository.class, ChatMemoryRepository.class })

and add a regression test where a user-provided ChatMemory bean still receives an auto-configured RedisChatMemoryRepository.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-redis/src/main/java/org/springframework/ai/model/chat/memory/repository/redis/autoconfigure/RedisChatMemoryRepositoryAutoConfiguration.java and compare the JDBC and Cassandra conditions. Add a regression test for a user-provided ChatMemory receiving the Redis repository, then run the relevant Redis repository auto-configuration tests; done means ChatMemory no longer suppresses repository creation.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring-boot
Domain
backend, testing
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.