Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.Exception: Protocol error: Got ($,[B@1669a570) as initial reply byte during hscan #229

Open
Darkhan97 opened this issue Jan 17, 2019 · 7 comments

Comments

@Darkhan97
Copy link

@debasishg I've got a exception similar to the which is = "java.lang.Exception: Protocol error: Got ($,[B@1669a570) as initial reply byte". I am using Redis server v=4.0.9, clitent "net.debasishg" %% "redisclient" % "3.9".
Exception was raised from here !!!
val scanTri:Option[(Option[Int], Option[List[Option[String]]])] = try {
r.hscan(key, cursor, s"${text}*", 500)
}
catch {
case e:Exception => {
println("Cosyak = " + e)
None
}
}
How can I deal with this?

@Oduig
Copy link

Oduig commented Apr 20, 2021

We had this problem and solved it. What appears to be the issue is code like either of the following examples.

val clientOutOfScope = redisPool.withClient { client => 
  client
}
clientOutOfScope.get(...)
redisPool.withClient { client => 
  Future {
    client.get(...)
  }
}

In both cases, the client is used in a situation where it is no longer in the withClient block, either used outside the block or in an asynchronous piece of code. At this point, the withClient block is finished and the client has been returned to the pool. If another thread then tries to use the pool, it may acquire the same client from the pool and the client will be shared across threads. This causes an internal buffer to get mixed up and results in the error above. It can also result in get, hget calls returning the value of a different key than the one requested.

Solution: do not use async code within withClient and never pass the client outside of its body scope.

@ShreyasTandale
Copy link

object RedisConnectionUtil extends RedisServiceProvider {
lazy val _redisMasterClientPool = new RedisClientPool(redisMasterUrl, 6379)
override def getRedisMasterClientPool(): RedisClientPool = _redisMasterClientPool
}
trait RedisCacheService {
def insert(key: CacheKey, values: List[String]): Boolean = {
val redisPool = redisConnectionUtil.getRedisMasterClientPool()
try {
redisPool.withClient(client => {
client.auth(redisConnectionUtil.getRedisAuth())
values.foreach(value => {
client.lpush(key, value)
})
})
logInfo(s"REDIS, push to cache successful for ${key}, values size = ${values.size}")
} catch {
case e: Exception => {
logError(s"Exception while pushing to Redis, key = ${key} message = ${e.getMessage}", e)

  }
}

}

I am using the redis client like this, still getting above error. Can you help me find out what is the issue?

@Oduig
Copy link

Oduig commented Aug 3, 2021

I don't see any problem with that code... Perhaps consider writing a minimal example with a test, and posting it to GitHub so it's reproducible.

@debasishg
Copy link
Owner

Yes, a minimal reproducible test case will help debug the problem.

@debasishg
Copy link
Owner

@Oduig Indeed .. a client escaping the scope of withClient is a problem.

@noahlz
Copy link

noahlz commented May 11, 2022

I just bumped into this issue because I was sending a list of items to redis in batches with list.grouped(500)... but forgot that grouped returns an Iterator that is "lazy" and doesn't comprehend the list until you call .toList. I was doing that outside the withClient block and therefore this error occurred. Very subtle!

@choijiho0021
Copy link

@Oduig
Thank you. it working,

// "Sometimes" Protocol error found code
  private val redisClient = pool.withClient { client => client }

  def jwtBlackList(key: Long, authObject: String) = {
    redisClient.rpush(key, authObject)
    redisClient.expire(key, 240)
  }
  

use only withClient "inside".

// Code changed after seeing your GitHub answer
  def jwtBlackList(key: Long, authObject: String) = {
    pool.withClient { redisClient =>
      redisClient.rpush(key, authObject)
      redisClient.expire(key, 240)
    }
  }

Now my code doesn't cause protocol errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants