redis/jedis · error · UnsupportedOperationException

binary ft.search is not implemented with resp3.

Error message

binary ft.search is not implemented with resp3.

What it means

The deprecated byte[]-based ftSearch(byte[], Query) in CommandObjects refuses to run under the RESP3 protocol because the binary search command path has not been implemented for RESP3. It throws UnsupportedOperationException before building the CommandObject.

Solutions

  1. Use the String-based ftSearch(String indexName, Query query) overload which supports RESP3
  2. Connect with RedisProtocol.RESP2 if the binary byte[] overload must be kept
  3. Encode index name once with SafeEncoder and switch code to the String API

Example fix

// before
SearchResult r = client.ftSearch("idx".getBytes(), query); // RESP3 -> throw
// after
SearchResult r = client.ftSearch("idx", query); // RESP3-safe
Defensive patterns

Strategy: fallback

Validate before calling

if (indexName instanceof byte[] && clientProtocol == RedisProtocol.RESP3) { /* switch to String overload or RESP2 */ }

Type guard

static boolean binarySearchUnsupported(RedisProtocol p) { return p == RedisProtocol.RESP3; }

Try / catch

try { return client.ftSearch(indexBytes, query); } catch (UnsupportedOperationException e) { return client.ftSearch(new String(indexBytes, StandardCharsets.UTF_8), query); }

Prevention

When it happens

Trigger: Calling ftSearch(byte[] indexName, Query query) while the client was negotiated/configured to use RedisProtocol.RESP3 (e.g. connected to Redis 6+ with default protocol RESP3).

Common situations: Migrating from legacy Jedis search usage to Redis 7+/RESP3 connections; using the deprecated binary overload because code passes byte[] index names; upgrading the server or setting protocol to RESP3 without noticing this overload is unimplemented.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08). Data as JSON: /api/errors/1ce69b9ba9e18e00. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/redis/clients/jedis/CommandObjects.java:4184

  }

  public final CommandObject<SearchResult> ftSearch(String indexName, String query, FTSearchParams params) {
    return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SEARCH, indexName)
        .add(query).addParams(params.dialectOptional(searchDialect.get())),
        getSearchResultBuilder(params.getReturnFieldDecodeMap(), () -> new SearchResultBuilder(
            !params.getNoContent(), params.getWithScores(), true, params.getReturnFieldDecodeMap())));
  }

  public final CommandObject<SearchResult> ftSearch(String indexName, Query query) {
    return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SEARCH, indexName)
        .addParams(query.dialectOptional(searchDialect.get())), getSearchResultBuilder(null,
        () -> new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), true)));
  }

  @Deprecated
  public final CommandObject<SearchResult> ftSearch(byte[] indexName, Query query) {
    if (protocol == RedisProtocol.RESP3) {
      throw new UnsupportedOperationException("binary ft.search is not implemented with resp3.");
    }
    return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.SEARCH, indexName)
        .addParams(query.dialectOptional(searchDialect.get())), getSearchResultBuilder(null,
        () -> new SearchResultBuilder(!query.getNoContent(), query.getWithScores(), false)));
  }

  public final CommandObject<String> ftExplain(String indexName, Query query) {
    return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.EXPLAIN, indexName)
        .addParams(query.dialectOptional(searchDialect.get())), BuilderFactory.STRING);
  }

  public final CommandObject<List<String>> ftExplainCLI(String indexName, Query query) {
    return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.EXPLAINCLI, indexName)
        .addParams(query.dialectOptional(searchDialect.get())), BuilderFactory.STRING_LIST);
  }

  public final CommandObject<AggregationResult> ftAggregate(String indexName, AggregationBuilder aggr) {
    return new CommandObject<>(checkAndRoundRobinSearchCommand(SearchCommand.AGGREGATE, indexName)

View on GitHub (pinned to 6dac31d4c2)