apache/hadoop · critical · IOException

Incorrect value for packet payload size: ${payloadLen}

Error message

Incorrect value for packet payload size: ${payloadLen}

What it means

Sanity check in readNextPacket(): payloadLen + headerLen must not overflow to negative nor exceed MAX_PACKET_SIZE (from dfs.client.max-packet-size-ish key DFS_DATA_TRANSFER_MAX_PACKET_SIZE, default 16 MiB as HdfsClientConfigKeys default). Its purpose is to prevent OOME from a hostile/garbage length field causing a huge buffer allocation.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/protocol/datatransfer/PacketReceiver.java:167

      // The "payload length" includes its own length. Therefore it
      // should never be less than 4 bytes
      throw new IOException("Invalid payload length " +
          payloadLen);
    }
    int dataPlusChecksumLen = payloadLen - Ints.BYTES;
    int headerLen = curPacketBuf.getShort();
    if (headerLen < 0) {
      throw new IOException("Invalid header length " + headerLen);
    }

    LOG.trace("readNextPacket: dataPlusChecksumLen={}, headerLen={}",
        dataPlusChecksumLen, headerLen);

    // Sanity check the buffer size so we don't allocate too much memory
    // and OOME.
    int totalLen = payloadLen + headerLen;
    if (totalLen < 0 || totalLen > MAX_PACKET_SIZE) {
      throw new IOException("Incorrect value for packet payload size: " +
                            payloadLen);
    }

    // Make sure we have space for the whole packet, and
    // read it.
    reallocPacketBuf(PacketHeader.PKT_LENGTHS_LEN +
        dataPlusChecksumLen + headerLen);
    curPacketBuf.clear();
    curPacketBuf.position(PacketHeader.PKT_LENGTHS_LEN);
    curPacketBuf.limit(PacketHeader.PKT_LENGTHS_LEN +
        dataPlusChecksumLen + headerLen);
    doReadFully(ch, in, curPacketBuf);
    curPacketBuf.flip();
    curPacketBuf.position(PacketHeader.PKT_LENGTHS_LEN);

    // Extract the header from the front of the buffer (after the length prefixes)
    byte[] headerBuf = new byte[headerLen];
    curPacketBuf.get(headerBuf);

View on GitHub (pinned to 2add963021)

Solutions

  1. If you deliberately increased chunk/packet sizes, raise dfs.datanode.transfer.max-packet-size consistently on BOTH ends within the same key/value.
  2. Otherwise treat as corruption: retry on another replica and check node/network health.
  3. Audit who can connect to data transfer ports if the pattern looks hostile.

Example fix

// hdfs-site.xml — must match on writer and reader sides
<property>
  <name>dfs.datanode.transfer.max-packet-size</name>
  <value>16777216</value> <!-- raise only if you also raised chunk sizes -->
</property>
Defensive patterns

Strategy: validation

Validate before calling

// Writer side: keep announced packet sizes within the reader cap before sending
int totalLen = payloadLen + headerLen;
if (totalLen < 0 || totalLen > 16 * 1024 * 1024) { // must match receiver's max-packet-size
  throw new IllegalArgumentException("packet too large: " + totalLen);
}

Try / catch

try { receiver.readNextPacket(); }
catch (IOException e) {
  if (e.getMessage().contains("packet payload size")) { /* abort stream; fix packet-size config mismatch */ }
}

Prevention

When it happens

Trigger: A length field claiming a packet larger than 16MB: sender configured with oversized chunk/packet sizes, corrupt length bytes, or an attacker crafting headers. Also integer overflow when payloadLen and headerLen sum past Integer.MAX_VALUE.

Common situations: Custom/incompatible writer that emits jumbo packets, corrupted streams, security scanning against the data-transfer port, or exotic configs raising chunk sizes beyond the reader cap.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/ccb5b2e37605f3ab. Report an issue: GitHub.