{"record":{"id":"cbc09393888c7a98","repo":"apache/beam","slug":"sortvalues-requires-its-input-to-use-kvcoder","errorCode":null,"errorMessage":"SortValues requires its input to use KvCoder","messagePattern":"SortValues requires its input 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":104,"sourceCode":"      throw new IllegalStateException(\n          \"the secondary key coder of SortValues must be deterministic\", e);\n    }\n\n    return input\n        .apply(\n            ParDo.of(\n                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  }","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/sorter/src/main/java/org/apache/beam/sdk/extensions/sorter/SortValues.java#L86-L122","documentation":"SortValues expects its input PCollection to be keyed data whose coder is a KvCoder<P, Iterable<...>> so it can statically extract the secondary key/value coders. If the input coder is not a KvCoder (e.g., an inferred coder like a custom or StructuralCoder), getSecondaryKeyValueCoder throws IllegalStateException because it cannot decompose the element type.","triggerScenarios":"Applying SortValues.perKey() to a PCollection<KV<P, Iterable<KV<S,V>>>> whose coder was set/inferred as something other than KvCoder — e.g., setCoder(myCustomKvLikeCoder), or input built through transforms that lose the KvCoder type information.","commonSituations":"Manually calling setCoder with a wrong coder; piping through a transform that re-infers coders; deserializing KV from a source that assigns a generic coder; test pipelines that construct PCollections without KvCoder.","solutions":["Ensure the input uses KvCoder: pCollection.setCoder(KvCoder.of(primaryCoder, IterableCoder.of(KvCoder.of(secondaryKeyCoder, valueCoder))))","Build the input with keyed transforms (WithKeys, GroupByKey) so Beam infers KvCoder naturally","If using a custom coder, make it a KvCoder subclass exposing getKeyCoder/getValueCoder","Inspect the actual coder with input.getCoder() and log it to find where the wrong coder is assigned"],"exampleFix":"// before\ninput.setCoder(new MyKvLikeCoder<P, Iterable<KV<S,V>>>());\n// after\ninput.setCoder(KvCoder.of(\n    primaryCoder,\n    IterableCoder.of(KvCoder.of(secondaryKeyCoder, valueCoder))));","handlingStrategy":"validation","validationCode":"if (!(input.getCoder() instanceof KvCoder)) { throw new IllegalStateException(\"SortValues input must use KvCoder; got \" + input.getCoder()); }","typeGuard":"static boolean hasKvCoder(PCollection<?> pc) { return pc.getCoder() instanceof KvCoder; }","tryCatchPattern":"try { SortValues.perKey(); } catch (IllegalStateException e) { if (e.getMessage().contains(\"KvCoder\")) { input.setCoder(KvCoder.of(pkCoder, IterableCoder.of(KvCoder.of(skCoder, vCoder)))); } else { throw e; } }","preventionTips":["Check input.getCoder() before keyed sort transforms","Let Beam infer KvCoder via WithKeys/GroupByKey rather than setting custom coders","Avoid setCoder with non-Kv coders on KV-typed PCollections","Add pipeline-construction unit tests asserting coder types"],"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"}