{"record":{"id":"40fb56ead08040a8","repo":"apache/beam","slug":"sortvalues-requires-the-values-be-encoded-with-iterablecoder","errorCode":null,"errorMessage":"SortValues requires the values be encoded with IterableCoder","messagePattern":"SortValues requires the values be encoded with IterableCoder","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/sorter/src/main/java/org/apache/beam/sdk/extensions/sorter/SortValues.java","lineNumber":111,"sourceCode":"                new SortValuesDoFn<>(\n                    sorterOptions, secondaryKeyCoder, getValueCoder(input.getCoder()))))\n        .setCoder(input.getCoder());\n  }\n\n  /** Retrieves the {@link Coder} for the secondary key-value pairs. */\n  @SuppressWarnings(\"unchecked\")\n  private static <PrimaryKeyT, SecondaryKeyT, ValueT>\n      KvCoder<SecondaryKeyT, ValueT> getSecondaryKeyValueCoder(\n          Coder<KV<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>>> inputCoder) {\n    if (!(inputCoder instanceof KvCoder)) {\n      throw new IllegalStateException(\"SortValues requires its input to use KvCoder\");\n    }\n    @SuppressWarnings(\"unchecked\")\n    KvCoder<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>> kvCoder =\n        (KvCoder<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>>) inputCoder;\n\n    if (!(kvCoder.getValueCoder() instanceof IterableCoder)) {\n      throw new IllegalStateException(\n          \"SortValues requires the values be encoded with IterableCoder\");\n    }\n    IterableCoder<KV<SecondaryKeyT, ValueT>> iterableCoder =\n        (IterableCoder<KV<SecondaryKeyT, ValueT>>) kvCoder.getValueCoder();\n\n    if (!(iterableCoder.getElemCoder() instanceof KvCoder)) {\n      throw new IllegalStateException(\n          \"SortValues requires the secondary key-value pairs to use KvCoder\");\n    }\n    return (KvCoder<SecondaryKeyT, ValueT>) iterableCoder.getElemCoder();\n  }\n\n  /** Retrieves the {@link Coder} for the secondary keys. */\n  private static <PrimaryKeyT, SecondaryKeyT, ValueT> Coder<SecondaryKeyT> getSecondaryKeyCoder(\n      Coder<KV<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>>> inputCoder) {\n    return getSecondaryKeyValueCoder(inputCoder).getKeyCoder();\n  }\n","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sorter/src/main/java/org/apache/beam/sdk/extensions/sorter/SortValues.java#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the value coder to IterableCoder.of(KvCoder.of(secondaryKeyCoder, valueCoder)) via setCoder","Produce the values through CoGroupByKey/GroupByKey-style pipelines that infer IterableCoder","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","Additionally ensure each element coder of the Iterable is itself a KvCoder (the next check in the same method)"],"exampleFix":"// before\ninput.setCoder(KvCoder.of(pkCoder, ListCoder.of(KvCoder.of(skCoder, vCoder))));\n// after\ninput.setCoder(KvCoder.of(pkCoder, IterableCoder.of(KvCoder.of(skCoder, vCoder))));","handlingStrategy":"validation","validationCode":"Coder<?> valueCoder = ((KvCoder<?, ?>) input.getCoder()).getValueCoder();\nif (!(valueCoder instanceof IterableCoder)) { throw new IllegalStateException(\"value must be IterableCoder, got \" + valueCoder); }","typeGuard":"static boolean hasIterableValueCoder(PCollection<?> pc) { return pc.getCoder() instanceof KvCoder && ((KvCoder<?, ?>) pc.getCoder()).getValueCoder() instanceof IterableCoder; }","tryCatchPattern":"try { SortValues.perKey(); } catch (IllegalStateException e) { if (e.getMessage().contains(\"IterableCoder\")) { input.setCoder(KvCoder.of(pkCoder, IterableCoder.of(kvElemCoder))); } else { throw e; } }","preventionTips":["Always use IterableCoder (not ListCoder/SetCoder) for per-key sorted values","Assert the full coder chain (KvCoder -> IterableCoder -> KvCoder) in tests before applying SortValues","Build per-key iterables via GroupByKey-family transforms so coders are inferred correctly","Log full coder chains when debugging coder-related IllegalStateExceptions"],"tags":["java","apache-beam","sorter","coder","type-mismatch"],"backgroundTag":"incompatible-source-type","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}