{"record":{"id":"b01072d0e84fc7bc","repo":"apache/beam","slug":"cannot-encode-a-null-kv","errorCode":null,"errorMessage":"cannot encode a null KV","messagePattern":"cannot encode a null KV","errorType":"exception","errorClass":"CoderException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/coders/KvCoder.java","lineNumber":70,"sourceCode":"\n  private final Coder<K> keyCoder;\n  private final Coder<V> valueCoder;\n\n  private KvCoder(Coder<K> keyCoder, Coder<V> valueCoder) {\n    this.keyCoder = keyCoder;\n    this.valueCoder = valueCoder;\n  }\n\n  @Override\n  public void encode(KV<K, V> kv, OutputStream outStream) throws IOException, CoderException {\n    encode(kv, outStream, Context.NESTED);\n  }\n\n  @Override\n  public void encode(KV<K, V> kv, OutputStream outStream, Context context)\n      throws IOException, CoderException {\n    if (kv == null) {\n      throw new CoderException(\"cannot encode a null KV\");\n    }\n    keyCoder.encode(kv.getKey(), outStream);\n    valueCoder.encode(kv.getValue(), outStream, context);\n  }\n\n  @Override\n  public KV<K, V> decode(InputStream inStream) throws IOException, CoderException {\n    return decode(inStream, Context.NESTED);\n  }\n\n  @Override\n  public KV<K, V> decode(InputStream inStream, Context context) throws IOException, CoderException {\n    K key = keyCoder.decode(inStream);\n    V value = valueCoder.decode(inStream, context);\n    return KV.of(key, value);\n  }\n\n  @Override","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/KvCoder.java#L52-L88","documentation":"KvCoder.encode refuses the null KV passed to it: it immediately delegates to keyCoder/valueCoder on kv.getKey()/getValue(), which would NPE, so it fails fast with CoderException instead. Use NullableCoder.of(KvCoder.of(...)) if null KVs are expected in the data.","triggerScenarios":"Invoking KvCoder.encode(null, out, context) directly, or a PCollection<KV<K,V>> element that is null reaching an encoding/shuffle stage.","commonSituations":"DoFns that map lookup misses to null KV instead of skipping them; building records where an optional key-value pair was modeled as a null KV.","solutions":["Filter out null KV elements (Filter.by(kv -> kv != null)) before grouping/encoding stages.","Emit an empty/sentinel KV instead of null from producing transforms.","Model optionality with Optional<KV<K,V>> and filter None cases out of the coded PCollection."],"exampleFix":"// before\nreturn hit == null ? null : KV.of(key, hit); // null KV later throws\n// after\nreturn hit == null ? null /* filtered below */ : KV.of(key, hit);\n.apply(Filter.by(kv -> kv != null));","handlingStrategy":"validation","validationCode":"if (kv != null) { coder.encode(kv, out, context); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter null KVs with Filter.by(kv -> kv != null) before shuffles.","Never return null KV from DoFns; emit only on hit.","Model optional pairs with a sentinel or Optional and filter before encoding."],"tags":["java","apache-beam","coders","null","kv"],"backgroundTag":"null-argument","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"}