{"record":{"id":"77d4f4e6b3347f5f","repo":"nathanmarz/storm","slug":"null-object-forbidded-in-message-batch","errorCode":null,"errorMessage":"null object forbidded in message batch","messagePattern":"null object forbidded in message batch","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"storm-netty/src/jvm/backtype/storm/messaging/netty/MessageBatch.java","lineNumber":42,"sourceCode":"import org.jboss.netty.buffer.ChannelBuffers;\nimport org.jboss.netty.channel.Channel;\n\nimport backtype.storm.messaging.TaskMessage;\n\nclass MessageBatch {\n    private int buffer_size;\n    private ArrayList<Object> msgs;\n    private int encoded_length;\n\n    MessageBatch(int buffer_size) {\n        this.buffer_size = buffer_size;\n        msgs = new ArrayList<Object>();\n        encoded_length = ControlMessage.EOB_MESSAGE.encodeLength();\n    }\n\n    void add(Object obj) {\n        if (obj == null)\n            throw new RuntimeException(\"null object forbidded in message batch\");\n\n        if (obj instanceof TaskMessage) {\n            TaskMessage msg = (TaskMessage)obj;\n            msgs.add(msg);\n            encoded_length += msgEncodeLength(msg);\n            return;\n        }\n\n        if (obj instanceof ControlMessage) {\n            ControlMessage msg = (ControlMessage)obj;\n            msgs.add(msg);\n            encoded_length += msg.encodeLength();\n            return;\n        }\n\n        throw new RuntimeException(\"Unsuppoted object type \"+obj.getClass().getName());\n    }\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-netty/src/jvm/backtype/storm/messaging/netty/MessageBatch.java#L24-L60","documentation":"MessageBatch.add accumulates TaskMessages and ControlMessages for one network batch. A null element cannot be encoded and would corrupt the batch, so add throws this RuntimeException at MessageBatch.java:42 when obj == null.","triggerScenarios":"Calling add(null) directly, or indirectly via tryAdd/takeMessages when a queue/iterator yields null elements (e.g. a poll on an empty buffer misused as a message).","commonSituations":"Draining a LinkedBlockingQueue with poll()/take() returning null sentinel values that then get added to the batch; custom batching code passing null placeholders; deserialization paths producing null messages.","solutions":["Null-check each message before adding it to the batch (skip nulls).","Fix the producer/queue so null never enters the message stream; use explicit sentinel objects instead.","In takeMessages/tryAdd wrappers, verify queue poll results before calling add."],"exampleFix":"// before\nTaskMessage msg = queue.poll();\nbatch.add(msg);\n// after\nTaskMessage msg = queue.poll();\nif (msg != null) {\n    batch.add(msg);\n}","handlingStrategy":"validation","validationCode":"if (message == null) return; // skip instead of adding to batch","typeGuard":"boolean isValidBatchEntry(Object o) {\n    return o instanceof TaskMessage || o instanceof ControlMessage;\n}","tryCatchPattern":"try {\n    batch.add(msg);\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"null object\")) {\n        LOG.warn(\"Skipped null message in batch\");\n    } else { throw e; }\n}","preventionTips":["Null-check queue poll()/take() results before adding to a batch.","Avoid null sentinels in message queues; use typed control messages.","Add unit tests for batch building with edge-case queue drains."],"tags":["netty","batching","null-check","messaging"],"backgroundTag":"null-argument","analyzedSha":"cdb116e942666973bc4eaa0df098d5bab82739e7","analyzedAt":"2026-09-12T14:30:00.714Z","contentChangedAt":"2026-09-12T14:30:00.714Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}