redis/jedis · error · IllegalArgumentException

HashImport ' ' expects values but got

Error message

HashImport '<name>' expects <size> values but got <valueCount>

What it means

HashImportSupport.checkArgs enforces that the number of values passed to a hash-import call exactly matches the declared size of the HashImport fieldset. If the caller supplies fewer or more values than the fieldset was created with, IllegalArgumentException is thrown before anything is sent to Redis. This protects against desynchronized field/value pairing.

Solutions

  1. Ensure the values collection length equals fieldset.size() before the call (values.size() == fieldset.size())
  2. Rebuild the fieldset from the same source data as the values so they stay in sync
  3. Log both fieldset.size() and values.size() at the call site to find where they diverge

Example fix

// before
List<String> values = rawValues.stream().filter(Objects::nonNull).collect(toList());
jedis.himport(namespace, key, fieldset, values); // expects fieldset.size(), got fewer
// after
List<String> values = rawValues.stream().filter(Objects::nonNull).collect(toList());
if (values.size() != fieldset.size()) {
  throw new IllegalArgumentException("values/fieldset mismatch: " + values.size() + " vs " + fieldset.size());
}
jedis.himport(namespace, key, fieldset, values);
Defensive patterns

Strategy: validation

Validate before calling

if (values.size() != fieldset.size()) {
  throw new IllegalArgumentException("expected " + fieldset.size() + " values, got " + values.size());
}

Try / catch

try {
  hashImportCall(fieldset, values);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("expects")) {
    log.error("fieldset/values count mismatch: {}", e.getMessage());
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling a hash-import API with a values array/collection whose length differs from fieldset.size() — e.g. the fieldset declares 5 hash fields but the caller passes 4 or 6 values in the corresponding varargs/Collection.

Common situations: Building the fieldset and the value list from different data sources that drifted out of sync; filtering nulls out of the values list after the fieldset was constructed; off-by-one bugs when appending a new field to one side only.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/HashImportSupport.java:22

 * {@code HIMPORT SET} helpers: client-side argument validation, and the per-connection
 * prepare-before-use that a {@code himportSet} {@link CommandObject}'s
 * {@linkplain CommandObject#getPreProcessHooks() pre-process hook} runs. The hook is invoked by
 * {@link Connection#executeCommand(CommandObject)} once the {@code CommandExecutor} has picked a
 * connection &mdash; so retry / cluster redirection / failover stay in force &mdash; injecting a
 * {@code PREPARE} on that connection just before the {@code SET} when the fieldset is not yet
 * prepared there.
 */
final class HashImportSupport {

  private HashImportSupport() {
  }

  static void checkArgs(HashImport fieldset, int valueCount) {
    if (fieldset.isDiscarded()) {
      throw new IllegalStateException("HashImport '" + fieldset.name() + "' has been discarded");
    }
    if (valueCount != fieldset.size()) {
      throw new IllegalArgumentException("HashImport '" + fieldset.name() + "' expects "
          + fieldset.size() + " values but got " + valueCount);
    }
  }

  /**
   * Prepare-before-use: if {@code fieldset} is not yet prepared on {@code connection}, send
   * {@code HIMPORT PREPARE} and record it in the connection's note. The PREPARE is built here, only
   * when actually needed &mdash; the common already-prepared case allocates nothing. The caller
   * must own the connection.
   */
  static void prepareBeforeUse(Connection connection, HashImport fieldset) {
    if (!connection.himportState().isPrepared(fieldset.name())) {
      connection.executeCommand(new CommandArguments(Protocol.Command.HIMPORT)
          .add(Protocol.Keyword.PREPARE).add(fieldset.name()).addObjects(fieldset.fields()));
      markPrepared(connection, fieldset);
    }
  }

View on GitHub (pinned to 6dac31d4c2)