Skip to content

IllegalStateException on connection with username/password: block()/blockFirst()/blockLast() are blocking, which is not supported in thread #3603

Closed

Description

@joefruland

Bug Report

Current Behavior

IllegalStateExceptions are being thrown when trying to establish connections to redis with a username/password since Lettuce 7 when using Spring WebFlux.

Stack trace
block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3
                                    reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:87)
                                                                                  reactor.core.publisher.Mono.block(Mono.java:1779)
                                                                          io.lettuce.core.RedisURI.getAuthority(RedisURI.java:951)
                                                                       io.lettuce.core.RedisURI.createUriString(RedisURI.java:812)
                                                                              io.lettuce.core.RedisURI.toString(RedisURI.java:1070)
                                                               io.lettuce.core.ConnectionBuilder.apply(ConnectionBuilder.java:115)
                                               io.lettuce.core.AbstractRedisClient.connectionBuilder(AbstractRedisClient.java:252)
                                   io.lettuce.core.cluster.RedisClusterClient.createConnectionBuilder(RedisClusterClient.java:901)
                                      io.lettuce.core.cluster.RedisClusterClient.connectStatefulAsync(RedisClusterClient.java:869)
                                        io.lettuce.core.cluster.RedisClusterClient.connectToNodeAsync(RedisClusterClient.java:563)
….core.cluster.PooledClusterConnectionProvider$DefaultClusterNodeConnectionFactory.apply(PooledClusterConnectionProvider.java:801)
….core.cluster.PooledClusterConnectionProvider$DefaultClusterNodeConnectionFactory.apply(PooledClusterConnectionProvider.java:775)
….lettuce.core.cluster.PooledClusterConnectionProvider$NodeConnectionPostProcessor.apply(PooledClusterConnectionProvider.java:741)
….lettuce.core.cluster.PooledClusterConnectionProvider$NodeConnectionPostProcessor.apply(PooledClusterConnectionProvider.java:712)
                       io.lettuce.core.internal.AsyncConnectionProvider.lambda$getSynchronizer$0(AsyncConnectionProvider.java:85)
                                      java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
                                io.lettuce.core.internal.AsyncConnectionProvider.getSynchronizer(AsyncConnectionProvider.java:83)
                                  io.lettuce.core.internal.AsyncConnectionProvider.getConnection(AsyncConnectionProvider.java:60)
              io.lettuce.core.cluster.PooledClusterConnectionProvider.getConnectionAsync(PooledClusterConnectionProvider.java:461)
          io.lettuce.core.cluster.PooledClusterConnectionProvider.getReadFromConnections(PooledClusterConnectionProvider.java:411)
               io.lettuce.core.cluster.PooledClusterConnectionProvider.getReadConnection(PooledClusterConnectionProvider.java:262)
              io.lettuce.core.cluster.PooledClusterConnectionProvider.getConnectionAsync(PooledClusterConnectionProvider.java:152)
                       io.lettuce.core.cluster.ClusterDistributionChannelWriter.doWrite(ClusterDistributionChannelWriter.java:182)
                         io.lettuce.core.cluster.ClusterDistributionChannelWriter.write(ClusterDistributionChannelWriter.java:116)
                                                        io.lettuce.core.RedisChannelHandler.dispatch(RedisChannelHandler.java:203)
                  io.lettuce.core.cluster.StatefulRedisClusterConnectionImpl.dispatch(StatefulRedisClusterConnectionImpl.java:247)
...

Input Code

Creating the RedisURI with a username and password is causing this code to run on connect which is calling the .block() method:

RedisCredentials creds = credentialsProvider.resolveCredentials().block();

Input Code
RedisURI redisURI = RedisURI.builder()
                .withHost(clusterConfigEndpoint)
                .withAuthentication(redisUsername, redisPassword)
                .withSsl(true)
                .build();

Expected behavior/code

There should be no calls to .block() when establishing the connection. This is causing reactor threads to throw exceptions.

Environment

  • Lettuce version(s): 7.2.1.RELEASE
  • Redis version: Valkey 8.1

Possible Solution

Remove the .block() call in the RedisURI.getAuthority method.

Activity

  1. added theissue type on Jan 6, 2026
  2. PreAgile commented on Mar 30, 2026

    @PreAgile
    Contributor

    Hi, I'd like to work on this issue.

    It looks like the .block() in RedisURI.getAuthority() is the cause here. I'll investigate a non-blocking fix
    that preserves existing behavior and add a regression test. Let me know if there are any caveats I should be
    aware of before I start.

  3. young0264 commented on May 15, 2026

    @young0264
    Contributor

    Hi @tishun,

    This looks like a blocking call is being introduced during RedisURI string/authority materialization in the connection setup path.

    From the stack trace, what stands out to me is:

    • ConnectionBuilder.apply(...) calls redisURI.toString()
    • RedisURI.toString() goes through the masking path
    • RedisURI.getAuthority() appears to resolve credentials via .block()

    That seems consistent with the IllegalStateException showing up when a new connection is created on a Reactor thread with username/password authentication configured.

    I previously contributed a related Lettuce change around moving DNS resolution onto the non-blocking path, so I’d be happy to take a closer look at this one as well.

    If this understanding matches the intended behavior, I can work on a fix and open a PR.

    Feel free to assign it to me if that works for you.

  4. tishun commented on May 21, 2026

    @tishun
    Collaborator

    FWIW @a-TODO-rov is currently maintaining the driver.

    @PreAgile and @young0264 please sync between each other - you can both work on the task if you want to, just send a PR when you are ready.

  5. young0264 commented on May 21, 2026

    @young0264
    Contributor

    Hi @PreAgile!

    Since you expressed interest in this issue first, I wanted to check with you before starting on my side.

    It looks like the maintainer is okay with moving forward on this issue. If you're planning to work on it, please feel free to take it and open a PR first.

    If you haven't started yet or don't have enough time to continue, I can take a first pass and open a PR. I'm also happy to collaborate on the fix or help review/test the PR if needed.

    Could you let me know how you'd like to proceed?

    Thanks!


    안녕하세요 @PreAgile님, 한국어로도 간단히 남깁니다.
    먼저 이슈에 관심을 표현해주셔서, 제가 작업을 시작하기 전에 먼저 의사를 여쭤보고 싶었습니다.
    진행하실 계획이 있으시면 먼저 PR을 올려주셔도 좋고, 아직 시작 전이시거나 시간이 부족하시다면 제가 먼저 작업해보겠습니다.
    필요하다면 수정 방향이나 테스트 쪽에서 같이 협업해도 좋을 것 같습니다.
    감사합니다!

  6. a-TODO-rov commented on May 21, 2026

    @a-TODO-rov
    Collaborator

    We should keep in mind, that this will be fixed with #3614 and you can actually see it being addressed here .
    However this changes will probably take effect from 8.0 forward and we should think about a solution for 7.x branch as well.
    So if you have some proposals on that one, i will be glad to review them.

  7. PreAgile commented on May 25, 2026

    @PreAgile
    Contributor

    PR #3762 is up. @young0264 — would love your review on the test cases in particular (the reactor-parallel scheduler regression test is the one I'd most want a second pair of eyes on). If you spot a different approach you'd prefer, very open to iterating on the PR before it's marked ready.

  8. young0264 commented on May 26, 2026

    @young0264
    Contributor

    Hi @PreAgile,

    I opened a small PR against your fork with additional test coverage for #3762: PreAgile#1
    It covers a few extra RedisURI masking scenarios around immediate/non-immediate credential providers.
    Please feel free to take whichever parts make sense for #3762.

    Thanks!

  9. a-TODO-rov commented on May 26, 2026

    @a-TODO-rov
    Collaborator

    Left review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions