Summary
Upgrading spring-data-redis from 4.0.6 to 4.1.0 (via the Spring Boot 4.0.6 → 4.1.0 BOM bump) causes a StackOverflowError inside DefaultedRedisConnection on RedisConnection.set(...) calls. Reverting to 4.0.6 resolves it immediately with no other code changes.
Environment
- spring-data-redis: 4.1.0 (regression), 4.0.6 (last known-good)
- Spring Boot: 4.1.0
- Redis client: Lettuce (default
LettuceConnectionFactory)
- Trigger path:
org.springframework.cache.CacheManager (Redis-backed) → RedisCache.put → RedisConnection.set(...), invoked here via a Camel SpringCacheIdempotentRepository write, but any Redis-backed @Cacheable/cache-put should reproduce it
Stack trace (prod, truncated — ~994 identical frames)
java.lang.StackOverflowError: null
at org.springframework.data.redis.connection.DefaultedRedisConnection.set(DefaultedRedisConnection.java:374)
at org.springframework.data.redis.connection.DefaultedRedisConnection.set(DefaultedRedisConnection.java:374)
... (repeats)
What we found comparing bytecode across releases
Decompiling DefaultedRedisConnection, RedisConnection, and RedisStringCommands from the published 4.0.5, 4.0.6, and 4.1.0 jars:
- 4.0.5 and 4.0.6 are byte-for-byte identical for
DefaultedRedisConnection and RedisConnection — no regression between those two.
- Going from 4.0.6 → 4.1.0,
RedisStringCommands changes:
set(byte[], byte[], Expiration, SetOption) / setGet(byte[], byte[], Expiration, SetOption) are replaced by new overloads taking SetCondition instead: set(byte[], byte[], SetCondition, Expiration) / setGet(byte[], byte[], SetCondition, Expiration).
- New default methods appear:
digest, delex, xDelEx, xAckDel, xTrim.
- We were not able to pin down the exact recursive pair from bytecode alone (the published jars ship without debug/line-number tables, so we can't map the stack trace's line 374 to a specific overload). Given the timing, our working theory is that the
set/setGet overload swap introduced a default-method cycle in DefaultedRedisConnection — e.g. one overload's default implementation now delegates to the other overload's default implementation, which delegates back — but this needs confirmation against the actual 4.1.0 source.
Impact
In our case this crashed a production financial-services payments pipeline (Redis-backed idempotent-write cache used in an Apache Camel SFTP polling route) — every scheduled poll thread died with this error for ~2.5 hours before we identified the Boot/spring-data-redis version bump as the cause and rolled it back.
Workaround
Pin spring-data-redis back to 4.0.6 while keeping Spring Boot on 4.1.0 (override the BOM-managed version). No other code changes needed to avoid the crash.
Ask
Could someone confirm whether this is a known issue with the set/setGet SetCondition refactor in 4.1.0, and whether a patch release is planned? Happy to provide a minimal reproduction if useful.
Summary
Upgrading
spring-data-redisfrom 4.0.6 to 4.1.0 (via the Spring Boot 4.0.6 → 4.1.0 BOM bump) causes aStackOverflowErrorinsideDefaultedRedisConnectiononRedisConnection.set(...)calls. Reverting to 4.0.6 resolves it immediately with no other code changes.Environment
LettuceConnectionFactory)org.springframework.cache.CacheManager(Redis-backed) →RedisCache.put→RedisConnection.set(...), invoked here via a CamelSpringCacheIdempotentRepositorywrite, but any Redis-backed@Cacheable/cache-put should reproduce itStack trace (prod, truncated — ~994 identical frames)
What we found comparing bytecode across releases
Decompiling
DefaultedRedisConnection,RedisConnection, andRedisStringCommandsfrom the published 4.0.5, 4.0.6, and 4.1.0 jars:DefaultedRedisConnectionandRedisConnection— no regression between those two.RedisStringCommandschanges:set(byte[], byte[], Expiration, SetOption)/setGet(byte[], byte[], Expiration, SetOption)are replaced by new overloads takingSetConditioninstead:set(byte[], byte[], SetCondition, Expiration)/setGet(byte[], byte[], SetCondition, Expiration).digest,delex,xDelEx,xAckDel,xTrim.set/setGetoverload swap introduced a default-method cycle inDefaultedRedisConnection— e.g. one overload's default implementation now delegates to the other overload's default implementation, which delegates back — but this needs confirmation against the actual 4.1.0 source.Impact
In our case this crashed a production financial-services payments pipeline (Redis-backed idempotent-write cache used in an Apache Camel SFTP polling route) — every scheduled poll thread died with this error for ~2.5 hours before we identified the Boot/spring-data-redis version bump as the cause and rolled it back.
Workaround
Pin
spring-data-redisback to 4.0.6 while keeping Spring Boot on 4.1.0 (override the BOM-managed version). No other code changes needed to avoid the crash.Ask
Could someone confirm whether this is a known issue with the
set/setGetSetConditionrefactor in 4.1.0, and whether a patch release is planned? Happy to provide a minimal reproduction if useful.