{"record":{"id":"acb8fe3996f761f8","repo":"apache/beam","slug":"sortvalues-requires-the-secondary-key-value-pairs-to-use","errorCode":null,"errorMessage":"SortValues requires the secondary key-value pairs to use KvCoder","messagePattern":"SortValues requires the secondary key-value pairs to use KvCoder","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":118,"sourceCode":"  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\n  /** Returns the {@code Coder} of the values associated with the secondary keys. */\n  private static <PrimaryKeyT, SecondaryKeyT, ValueT> Coder<ValueT> getValueCoder(\n      Coder<KV<PrimaryKeyT, Iterable<KV<SecondaryKeyT, ValueT>>>> inputCoder) {\n    return getSecondaryKeyValueCoder(inputCoder).getValueCoder();\n  }\n\n  private static <T> T elementOf(Coder<T> coder, byte[] bytes) throws CoderException {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sorter/src/main/java/org/apache/beam/sdk/extensions/sorter/SortValues.java#L100-L136","documentation":"SortValues only works on PCollections whose values are encoded as an iterable of KV pairs wrapped in a KvCoder, because it must obtain typed coders for the secondary key and value to feed the external sort. getSecondaryKeyValueCoder casts the element coder of the IterableCoder to KvCoder and throws IllegalStateException when the cast fails. This guards the downstream sorting transform against a coder it cannot introspect.","triggerScenarios":"Applying SortValues to a PCollection created from a source whose values use IterableCoder<KV<K,V>> but whose element coder is not a KvCoder — e.g. a custom Coder, a CoGbkResult-like coder, or a coder inferred as a generic iterable coder rather than KvCoder.of(k,v).","commonSituations":"Developers pipe in results of a CoGroupByKey or build PCollections manually and set an explicit custom coder for the KV pairs; or a DoFn output's default coder resolves to something other than KvCoder (e.g. after a map that erases type information).","solutions":["Ensure the value PCollection's element coder is KvCoder.of(secondaryKeyCoder, valueCoder) via pipeline.apply(..., PCollection.setCoder(KvCoder.of(...))) or CoderRegistry inference.","Check what the values actually are: SortValues expects values of type Iterable<KV<SecondaryKeyT, ValueT>>; fix upstream types so iterable elements are genuine KV pairs.","If using a custom coder wrapper, switch to KvCoder or supply coders explicitly through SortValues' typed construction instead of relying on inference."],"exampleFix":"// before\nPCollection<KV<byte[], Iterable<KV<String, Integer>>>> sorted =\n    input.apply(\"sort\", SortValues.create()); // elem coder not KvCoder\n\n// after\nPCollection<KV<byte[], Iterable<KV<String, Integer>>>> sorted =\n    input.setCoder(KvCoder.of(\n        ByteArrayCoder.of(),\n        IterableCoder.of(KvCoder.of(StringUtf8Coder.of(), VarIntCoder.of()))))\n      .apply(\"sort\", SortValues.create());","handlingStrategy":"validation","validationCode":"Coder<?> valueCoder = input.getCoder();\nif (!(valueCoder instanceof KvCoder)) throw new IllegalArgumentException(\n    \"SortValues input must be encoded with KvCoder, got: \" + valueCoder);\nKvCoder<?, ?> kv = (KvCoder<?, ?>) valueCoder;\nif (!(kv.getValueCoder() instanceof IterableCoder)) throw new IllegalArgumentException(\n    \"SortValues values must be IterableCoder\");\nIterableCoder<?, ?> it = (IterableCoder<?, ?>) kv.getValueCoder();\nif (!(it.getElemCoder() instanceof KvCoder)) throw new IllegalArgumentException(\n    \"SortValues secondary pairs must use KvCoder, got: \" + it.getElemCoder());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set explicit coders with KvCoder/IterableCoder when feeding SortValues","Check coder inference with PCollection.getCoder() during pipeline debugging","Avoid custom coder wrappers around KV pairs"],"tags":["apache-beam","coder","java","sort"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}