Skip to content

bug: ClassCastException when using AutoComplete with both withScore() and withPayload() options #673

@vovasalyha

Description

@vovasalyha

When using the autocomplete feature with both .withScore() and .withPayload() options enabled, a ClassCastException occurs. The application throws an error indicating that redis.clients.jedis.resps.Tuple cannot be cast to java.lang.String.

Steps to Reproduce (Example from the docs)

  1. Create an entity with @AutoComplete and @AutoCompletePayload annotations:
@Document
public class Airport {
  @Id
  private String id;

  @AutoComplete
  private String name;

  @AutoCompletePayload("name")  // Links to the "name" autocomplete field
  private String code;

  @AutoCompletePayload("name")
  private String city;

  @AutoCompletePayload("name")
  private String country;
}
  1. Use autocomplete with both score and payload options:
AutoCompleteOptions options = AutoCompleteOptions.get()
  .fuzzy()          // Enable fuzzy matching
  .withScore()      // Include relevance scores
  .withPayload()    // Include payload data
  .limit(10);       // Limit to 10 results

List<Suggestion> suggestions = airportRepository.autoCompleteName("john f k", options);

Expected Behavior

The autocomplete should return suggestions with both score and payload data.

Actual Behavior

The following exception is thrown:

java.lang.ClassCastException: class redis.clients.jedis.resps.Tuple cannot be cast to class java.lang.String
      at org.springframework.data.redis.serializer.StringRedisSerializer.serialize(StringRedisSerializer.java:36)
      at org.springframework.data.redis.core.AbstractOperations.rawHashKey(AbstractOperations.java:187)
      at org.springframework.data.redis.core.DefaultHashOperations.get(DefaultHashOperations.java:58)
      at com.redis.om.spring.ops.search.SearchOperationsImpl.lambda$getSuggestion$0(SearchOperationsImpl.java:138)

Root Cause Analysis

In SearchOperationsImpl.java, when both withScore() and withPayload() are enabled, the code receives suggestions as List<Tuple> objects. However, on line 138, it incorrectly passes the entire Tuple object as a hash key:

Object payload = template.opsForHash().get(payLoadKey, suggestion); // suggestion here is a Tuple, but opsForHash().get() expects a String key

The equivalent code path without scores (line 154) works because suggestion is already a String in that case.

Proposed Solution

The fix appears straightforward - extract the element from the Tuple before using it as a hash key:

Object payload = template.opsForHash().get(payLoadKey, suggestion.getElement());

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions