{"record":{"id":"2a5e717724e57862","repo":"apache/beam","slug":"cannot-encode-a-null-map","errorCode":null,"errorMessage":"cannot encode a null Map","messagePattern":"cannot encode a null Map","errorType":"exception","errorClass":"CoderException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/coders/MapCoder.java","lineNumber":74,"sourceCode":"\n  private Coder<K> keyCoder;\n  private Coder<V> valueCoder;\n\n  private MapCoder(Coder<K> keyCoder, Coder<V> valueCoder) {\n    this.keyCoder = keyCoder;\n    this.valueCoder = valueCoder;\n  }\n\n  @Override\n  public void encode(Map<K, V> map, OutputStream outStream) throws IOException, CoderException {\n    encode(map, outStream, Context.NESTED);\n  }\n\n  @Override\n  public void encode(Map<K, V> map, OutputStream outStream, Context context)\n      throws IOException, CoderException {\n    if (map == null) {\n      throw new CoderException(\"cannot encode a null Map\");\n    }\n\n    int size = map.size();\n    BitConverters.writeBigEndianInt(size, outStream);\n    if (size == 0) {\n      return;\n    }\n\n    // Since we handled size == 0 above, entry is guaranteed to exist before and after loop\n    Iterator<Entry<K, V>> iterator = map.entrySet().iterator();\n    Entry<K, V> entry = iterator.next();\n    while (iterator.hasNext()) {\n      keyCoder.encode(entry.getKey(), outStream);\n      valueCoder.encode(entry.getValue(), outStream);\n      entry = iterator.next();\n    }\n\n    keyCoder.encode(entry.getKey(), outStream);","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/coders/MapCoder.java#L56-L92","documentation":"MapCoder's encode() refuses to encode a null Map. Beam coders encode values into a byte stream for serialization between pipeline stages; a null has no wire representation here, so the coder throws CoderException early rather than emitting a corrupt stream. Use NullableCoder to wrap the MapCoder if nulls must round-trip.","triggerScenarios":"Calling MapCoder.of(kCoder, vCoder).encode(null, out, Context.OUTER), directly or via a pipeline element whose output is a null Map.","commonSituations":"PCollection of Map<K,V> where a DoFn emits null for missing data; deserialized records with absent maps; schema/Java bean fields defaulted to null.","solutions":["Never emit null maps; replace them with Collections.emptyMap() before encoding","Wrap the coder with NullableCoder.of(mapCoder) so nulls are encoded as a flag byte","Guard in the DoFn: emit an empty map or skip the element when the map is null"],"exampleFix":"// before\nout.add(null);\n// after\nout.add(record.getMap() == null ? Collections.emptyMap() : record.getMap());","handlingStrategy":"validation","validationCode":"if (map == null) { map = Collections.emptyMap(); } // or throw a clear app-level error","typeGuard":"boolean isEncodable(java.util.Map<?,?> m) { return m != null; }","tryCatchPattern":"try { coder.encode(map, out, Context.OUTER); } catch (CoderException e) { /* handle null or encoding failure */ }","preventionTips":["Default map fields to empty maps at construction, not null","Wrap map coders in NullableCoder when null is a valid domain value","Add a DoFn-level null check before emitting maps"],"tags":["java","beam","coders","null"],"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"}