apache/beam · error · IllegalStateException

SortValues requires the values be encoded with IterableCoder

Error message

SortValues requires the values be encoded with IterableCoder

What it means

After confirming the input coder is a KvCoder, SortValues requires the value side to be an Iterable of KV pairs encoded with IterableCoder, since per-key sorting operates on collections of secondary key-value pairs. getSecondaryKeyValueCoder throws IllegalStateException when kvCoder.getValueCoder() is not an IterableCoder because it cannot extract the element coder of the sorted collection.

Source

Thrown at sdks/java/extensions/sorter/src/main/java/org/apache/beam/sdk/extensions/sorter/SortValues.java:111

                new SortValuesDoFn<>(
                    sorterOptions, secondaryKeyCoder, getValueCoder(input.getCoder()))))
        .setCoder(input.getCoder());
  }

  /** Retrieves the {@link Coder} for the secondary key-value pairs. */
  @SuppressWarnings("unchecked")
  private static <PrimaryKeyT, SecondaryKeyT, ValueT>
      KvCoder<SecondaryKeyT, ValueT> getSecondaryKeyValueCoder(
          Coder<KV<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>>> inputCoder) {
    if (!(inputCoder instanceof KvCoder)) {
      throw new IllegalStateException("SortValues requires its input to use KvCoder");
    }
    @SuppressWarnings("unchecked")
    KvCoder<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>> kvCoder =
        (KvCoder<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>>) inputCoder;

    if (!(kvCoder.getValueCoder() instanceof IterableCoder)) {
      throw new IllegalStateException(
          "SortValues requires the values be encoded with IterableCoder");
    }
    IterableCoder<KV<SecondaryKeyT, ValueT>> iterableCoder =
        (IterableCoder<KV<SecondaryKeyT, ValueT>>) kvCoder.getValueCoder();

    if (!(iterableCoder.getElemCoder() instanceof KvCoder)) {
      throw new IllegalStateException(
          "SortValues requires the secondary key-value pairs to use KvCoder");
    }
    return (KvCoder<SecondaryKeyT, ValueT>) iterableCoder.getElemCoder();
  }

  /** Retrieves the {@link Coder} for the secondary keys. */
  private static <PrimaryKeyT, SecondaryKeyT, ValueT> Coder<SecondaryKeyT> getSecondaryKeyCoder(
      Coder<KV<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>>> inputCoder) {
    return getSecondaryKeyValueCoder(inputCoder).getKeyCoder();
  }

View on GitHub (pinned to 12126d8942)

Solutions

  1. Set the value coder to IterableCoder.of(KvCoder.of(secondaryKeyCoder, valueCoder)) via setCoder
  2. Produce the values through CoGroupByKey/GroupByKey-style pipelines that infer IterableCoder
  3. If the value is a List, wrap/convert it to a coder-compatible Iterable representation (IterableCoder) or buffer into a re-batched PCollection with the correct coder
  4. Additionally ensure each element coder of the Iterable is itself a KvCoder (the next check in the same method)

Example fix

// before
input.setCoder(KvCoder.of(pkCoder, ListCoder.of(KvCoder.of(skCoder, vCoder))));
// after
input.setCoder(KvCoder.of(pkCoder, IterableCoder.of(KvCoder.of(skCoder, vCoder))));
Defensive patterns

Strategy: validation

Validate before calling

Coder<?> valueCoder = ((KvCoder<?, ?>) input.getCoder()).getValueCoder();
if (!(valueCoder instanceof IterableCoder)) { throw new IllegalStateException("value must be IterableCoder, got " + valueCoder); }

Type guard

static boolean hasIterableValueCoder(PCollection<?> pc) { return pc.getCoder() instanceof KvCoder && ((KvCoder<?, ?>) pc.getCoder()).getValueCoder() instanceof IterableCoder; }

Try / catch

try { SortValues.perKey(); } catch (IllegalStateException e) { if (e.getMessage().contains("IterableCoder")) { input.setCoder(KvCoder.of(pkCoder, IterableCoder.of(kvElemCoder))); } else { throw e; } }

Prevention

When it happens

Trigger: Applying SortValues.perKey() where the value coder is ListCoder, CollectionCoder, a custom iterable coder, or any non-IterableCoder — e.g., input.setCoder(KvCoder.of(pkCoder, ListCoder.of(kvCoder))) instead of IterableCoder.

Common situations: Manually setting the value coder to ListCoder or SetCoder; keys grouped through a custom combine that emits lists; using a coder registry that maps the value type to a non-Iterable coder.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/40fb56ead08040a8. Report an issue: GitHub.