redis/jedis · error · IllegalStateException

Unrecognized header

Error message

Unrecognized header: ${header}

What it means

SEARCH ProfilingBuilderFactory/SuggestBuilder's build() parses the reply of an FT.SUGGET-style/suffix command expecting the first KeyValue's key to be the RESULTS header. An IllegalStateException is thrown when the reply's header does not match, meaning the server response shape differs from what the builder expects.

Solutions

  1. Align RediSearch module and Jedis versions so reply formats match
  2. Verify you are invoking the correct command/API whose reply format is RESULTS-prefixed
  3. Inspect the raw reply (e.g. via a lower-level sendCommand) to confirm the actual server response shape

Example fix

// before
Object reply = connection.sendCommand(ProfilerCommand.LEX...);
// wrong reply fed to builder expecting RESULTS header
// after
// use the matching command/API or upgrade client so header matches RESULTS
Defensive patterns

Strategy: validation

Validate before calling

// confirm reply shape before building
if (!(raw instanceof java.util.List) || ((java.util.List<?>) raw).isEmpty()) throw new IllegalStateException("unexpected empty reply");

Prevention

When it happens

Trigger: Calling the associated search profiling/suggestion API whose raw reply's first element is not the expected RESULTS KeyValue — e.g. running against a server version with a different response format or a wrong command reply reaching the builder.

Common situations: RediSearch server/client version mismatch; custom modules or proxies altering reply layout; passing the builder the wrong command's reply.

Related errors


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/search/SearchBuilderFactory.java:52

    }
  };

  public static final Builder<Map<String, Map<String, Double>>> SEARCH_SPELLCHECK_RESPONSE
      = new Builder<Map<String, Map<String, Double>>>() {

    private static final String TERM = "TERM";
    private static final String RESULTS = "results";

    @Override
    public Map<String, Map<String, Double>> build(Object data) {
      List rawDataList = (List) data;
      if (rawDataList.isEmpty()) return Collections.emptyMap();

      if (rawDataList.get(0) instanceof KeyValue) {
        KeyValue rawData = (KeyValue) rawDataList.get(0);
        String header = STRING.build(rawData.getKey());
        if (!RESULTS.equals(header)) {
          throw new IllegalStateException("Unrecognized header: " + header);
        }

        return ((List<KeyValue>) rawData.getValue()).stream().collect(Collectors.toMap(
            rawTerm -> STRING.build(rawTerm.getKey()),
            rawTerm -> ((List<List<KeyValue>>) rawTerm.getValue()).stream()
                .collect(Collectors.toMap(entry -> STRING.build(entry.get(0).getKey()),
                      entry -> BuilderFactory.DOUBLE.build(entry.get(0).getValue()))),
            (x, y) -> x, LinkedHashMap::new));
      }

      Map<String, Map<String, Double>> returnTerms = new LinkedHashMap<>(rawDataList.size());

      for (Object rawData : rawDataList) {
        List<Object> rawElements = (List<Object>) rawData;

        String header = STRING.build(rawElements.get(0));
        if (!TERM.equals(header)) {
          throw new IllegalStateException("Unrecognized header: " + header);

View on GitHub (pinned to 6dac31d4c2)