{"record":{"id":"8ab61b7d991a6b2d","repo":"apache/beam","slug":"groupbyencryptedkey-requires-its-input-to-use-kvcoder","errorCode":null,"errorMessage":"GroupByEncryptedKey requires its input to use KvCoder","messagePattern":"GroupByEncryptedKey requires its input to use KvCoder","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/GroupByEncryptedKey.java","lineNumber":105,"sourceCode":"   * @param gbk The custom GBK transform to use in the middle of the GBEK.\n   * @param <K> The type of the keys in the input PCollection.\n   * @param <V> The type of the values in the input PCollection.\n   * @return A {@link GroupByEncryptedKey} transform.\n   */\n  public static <K, V> GroupByEncryptedKey<K, V> createWithCustomGbk(\n      Secret hmacKey,\n      PTransform<\n              PCollection<KV<byte[], KV<byte[], byte[]>>>,\n              PCollection<KV<byte[], Iterable<KV<byte[], byte[]>>>>>\n          gbk) {\n    return new GroupByEncryptedKey<>(hmacKey, gbk);\n  }\n\n  @Override\n  public PCollection<KV<K, Iterable<V>>> expand(PCollection<KV<K, V>> input) {\n    Coder<KV<K, V>> inputCoder = input.getCoder();\n    if (!(inputCoder instanceof KvCoder)) {\n      throw new IllegalStateException(\"GroupByEncryptedKey requires its input to use KvCoder\");\n    }\n    KvCoder<K, V> inputKvCoder = (KvCoder<K, V>) inputCoder;\n    Coder<K> keyCoder = inputKvCoder.getKeyCoder();\n\n    try {\n      keyCoder.verifyDeterministic();\n    } catch (NonDeterministicException e) {\n      throw new IllegalStateException(\n          \"the keyCoder of a GroupByEncryptedKey must be deterministic\", e);\n    }\n\n    Coder<V> valueCoder = inputKvCoder.getValueCoder();\n\n    PCollection<KV<byte[], Iterable<KV<byte[], byte[]>>>> grouped =\n        input\n            .apply(\n                \"EncryptMessage\",\n                ParDo.of(new EncryptMessage<>(this.hmacKey, keyCoder, valueCoder)))","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/GroupByEncryptedKey.java#L87-L123","documentation":"GroupByEncryptedKey needs the key coder to inspect and verify key encoding (determinism check, key encryption). If the input PCollection<KV<K,V>> coder is not a KvCoder, it cannot obtain the key coder and expand() throws IllegalStateException.","triggerScenarios":"Applying GroupByEncryptedKey to a PCollection whose coder was overridden with a non-KvCoder, or whose upstream transform inferred something other than KvCoder for the KV elements.","commonSituations":"Manual setCoder with a custom coder; custom sources or transforms emitting KV with a bespoke coder; raw KV types erasing the coder inference.","solutions":["Ensure the input is a standard KV PCollection with inferred KvCoder (remove explicit setCoder calls)","Explicitly set KvCoder: input.setCoder(KvCoder.of(keyCoder, valueCoder)) before applying GroupByEncryptedKey","Verify the upstream transform produces KV<K,V> with proper generics so coder inference yields KvCoder"],"exampleFix":"// before\ninput.setCoder(new MyCustomCoder<KV<K,V>>());\ninput.apply(GroupByEncryptedKey.create());\n// after\ninput.setCoder(KvCoder.of(keyCoder, valueCoder));\ninput.apply(GroupByEncryptedKey.create());","handlingStrategy":"type-guard","validationCode":"// Verify KvCoder before applying GroupByEncryptedKey\nif (!(input.getCoder() instanceof KvCoder)) {\n  throw new IllegalStateException(\"input must use KvCoder\");\n}","typeGuard":"boolean hasKvCoder(PCollection<KV<K,V>> in) {\n  return in.getCoder() instanceof KvCoder;\n}","tryCatchPattern":"try { out = input.apply(GroupByEncryptedKey.create()); }\ncatch (IllegalStateException e) { // set KvCoder and retry\n  input.setCoder(KvCoder.of(keyCoder, valueCoder));\n  out = input.apply(GroupByEncryptedKey.create());\n}","preventionTips":["Never override a KV PCollection's coder with a non-KvCoder","Verify the upstream transform produces standard KV types so inference yields KvCoder","Call keyCoder.verifyDeterministic() early in pipeline construction to surface related coder issues upfront"],"tags":["java","apache-beam","coder","kv","validation"],"backgroundTag":"type-mismatch","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"}