{"record":{"id":"091b9c2eb46a4ab9","repo":"apache/beam","slug":"cannot-encode-a-null-solrdocument","errorCode":null,"errorMessage":"cannot encode a null SolrDocument","messagePattern":"cannot encode a null SolrDocument","errorType":"exception","errorClass":"CoderException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/solr/src/main/java/org/apache/beam/sdk/io/solr/JavaBinCodecCoder.java","lineNumber":56,"sourceCode":"import org.apache.solr.common.SolrInputDocument;\nimport org.apache.solr.common.util.JavaBinCodec;\n\n/** A {@link Coder} that encodes using {@link JavaBinCodec}. */\nclass JavaBinCodecCoder<T> extends AtomicCoder<T> {\n  private final Class<T> clazz;\n\n  private JavaBinCodecCoder(Class<T> clazz) {\n    this.clazz = clazz;\n  }\n\n  public static <T> JavaBinCodecCoder<T> of(Class<T> clazz) {\n    return new JavaBinCodecCoder<>(clazz);\n  }\n\n  @Override\n  public void encode(T value, OutputStream outStream) throws IOException {\n    if (value == null) {\n      throw new CoderException(\"cannot encode a null SolrDocument\");\n    }\n\n    ByteArrayOutputStream baos = new ByteArrayOutputStream();\n    JavaBinCodec codec = new JavaBinCodec();\n    codec.marshal(value, baos);\n\n    byte[] bytes = baos.toByteArray();\n    VarInt.encode(bytes.length, outStream);\n    outStream.write(bytes);\n  }\n\n  @Override\n  public T decode(InputStream inStream) throws IOException {\n    DataInputStream in = new DataInputStream(inStream);\n\n    int len = VarInt.decodeInt(in);\n    if (len < 0) {\n      throw new CoderException(\"Invalid encoded SolrDocument length: \" + len);","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/solr/src/main/java/org/apache/beam/sdk/io/solr/JavaBinCodecCoder.java#L38-L74","documentation":"JavaBinCodecCoder serializes SolrDocument values using Solr's JavaBinCodec, which cannot represent null documents. The coder explicitly rejects null input with a CoderException during encode to keep the length-prefixed wire format valid.","triggerScenarios":"A PCollection fed to SolrIO.write() contains a null element, and Beam invokes JavaBinCodecCoder.encode(null, out) while materializing or serializing the record between stages.","commonSituations":"Upstream DoFns or joins emitting null documents instead of dropping them; accidental null entries after parsing/transform steps; deserialization of sparse data producing nulls before the Solr sink.","solutions":["Filter null elements before the write: PCollection.filter(doc -> doc != null)","Fix the upstream transform that produces null SolrDocuments","If nulls are meaningful, map them to an empty SolrDocument or a sentinel before the sink"],"exampleFix":"// before\npipeline.apply(SolrIO.write(solrIO)); // collection may contain nulls\n// after\ninput.apply(\"DropNullDocs\", Filter.by(doc -> doc != null))\n     .apply(SolrIO.write(solrIO));","handlingStrategy":"validation","validationCode":"if (doc == null) {\n  throw new IllegalArgumentException(\"SolrDocument must not be null before encode\");\n}","typeGuard":"boolean isValidDoc(SolrDocument d) { return d != null; }","tryCatchPattern":"try {\n  coder.encode(doc, out);\n} catch (CoderException e) {\n  LOG.error(\"Null or invalid SolrDocument passed to JavaBinCodecCoder\", e);\n  throw e;\n}","preventionTips":["Filter null elements upstream before SolrIO.write()","Add a Filter.by(Objects::nonNull) step before the sink","Audit transforms for paths that can emit null","Validate documents against the Solr schema before writing"],"tags":["java","beam","solr","null","coder"],"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"}