apache/hadoop · error · java.io.IOException

Op {opCodeByte} has size {opLength}, but maxOpSize = {maxOpS

Error message

Op {opCodeByte} has size {opLength}, but maxOpSize = {maxOpSize}

What it means

LengthPrefixedReader.decodeOpFrame() validates the record's 4-byte length before decoding: opLength = stored length + 5 (1 opcode byte + 4 checksum bytes). It must not exceed maxOpSize, configured by dfs.namenode.max.op.size (default 50 MB, DFSConfigKeys.java:1290). The guard exists because a garbage length used to drive a huge allocation and OOM the NameNode/JournalNode when reading corrupt data.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSEditLogOp.java:5249

      byte opCodeByte;
      try {
        opCodeByte = in.readByte();
      } catch (EOFException eof) {
        // EOF at an opcode boundary is expected.
        return HdfsServerConstants.INVALID_TXID;
      }
      if (opCodeByte == FSEditLogOpCodes.OP_INVALID.getOpCode()) {
        verifyTerminator();
        return HdfsServerConstants.INVALID_TXID;
      }
      // Here, we verify that the Op size makes sense and that the
      // data matches its checksum before attempting to construct an Op.
      // This is important because otherwise we may encounter an
      // OutOfMemoryException which could bring down the NameNode or
      // JournalNode when reading garbage data.
      int opLength =  in.readInt() + OP_ID_LENGTH + CHECKSUM_LENGTH;
      if (opLength > maxOpSize) {
        throw new IOException("Op " + (int)opCodeByte + " has size " +
            opLength + ", but maxOpSize = " + maxOpSize);
      } else  if (opLength < MIN_OP_LENGTH) {
        throw new IOException("Op " + (int)opCodeByte + " has size " +
            opLength + ", but the minimum op size is " + MIN_OP_LENGTH);
      }
      long txid = in.readLong();
      // Verify checksum
      in.reset();
      in.mark(maxOpSize);
      checksum.reset();
      for (int rem = opLength - CHECKSUM_LENGTH; rem > 0;) {
        int toRead = Math.min(temp.length, rem);
        IOUtils.readFully(in, temp, 0, toRead);
        checksum.update(temp, 0, toRead);
        rem -= toRead;
      }
      int expectedChecksum = in.readInt();
      int calculatedChecksum = (int)checksum.getValue();

View on GitHub (pinned to 2add963021)

Solutions

  1. Determine which case you are in with 'hdfs offlineEditsViewer -i <edits> -o out.xml' before changing anything
  2. If the op is legitimate, set dfs.namenode.max.op.size above the record size in hdfs-site.xml on the NameNode (and any tool reading the log) and restart
  3. If corrupt, run 'hdfs namenode -recover' to skip the record, or restore a healthy copy of the segment from QJM majority

Example fix

<!-- before: hdfs-site.xml (default cap = 50 MB) -->
<!-- after -->
<property>
  <name>dfs.namenode.max.op.size</name>
  <value>134217728</value>
</property>
Defensive patterns

Strategy: retry

Validate before calling

# before replay of segments known to carry very large ops:
# check largest segment size and raise the cap above it
ls -l /dfs/name/current/edits_*
# hdfs-site.xml: dfs.namenode.max.op.size must exceed the largest single record

Try / catch

try {
  reader.readOp(); // maxOpSize from dfs.namenode.max.op.size
} catch (IOException e) {
  if (e.getMessage().contains("but maxOpSize =")) {
    if (offlineEditsViewerConfirmsLegitLargeOp) {
      reader.setMaxOpSize(largerLimit); // or raise dfs.namenode.max.op.size and restart
      // then retry the replay
    } else {
      // corruption: recover or restore a clean segment
    }
  } else { throw e; }
}

Prevention

When it happens

Trigger: A corrupt length int in the stream (bit rot, torn write, misalignment) produces an absurd opLength; rarely, a legitimate record larger than 50 MB (an extreme payload) exceeds the default cap on a stock configuration.

Common situations: Corrupt journal segments; clusters carrying pathologically large ops (huge concat/rename payloads) replayed with default settings; tools reading the same segments inherit the same limit.

Related errors


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