apache/hadoop · error · IOException

Unexpected extra bytes from input stream for {mapId}

Error message

Unexpected extra bytes from input stream for {mapId}

What it means

InMemoryMapOutput.load() reads exactly decompressedLength bytes into memory, then calls input.read() once to force the decompressor to drain trailing bytes and keep the stream in sync. A non-negative result means the decompressed stream contains more data than the shuffle header announced, i.e. corrupt length or payload. The scheduler treats it as a fetch failure and re-fetches the map output.

Source

Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/task/reduce/InMemoryMapOutput.java:105

      input = codec.createInputStream(input, decompressor);
    }
  
    try {
      IOUtils.readFully(input, memory, 0, memory.length);
      metrics.inputBytes(memory.length);
      reporter.progress();
      LOG.info("Read " + memory.length + " bytes from map-output for " +
                getMapId());

      /**
       * We've gotten the amount of data we were expecting. Verify the
       * decompressor has nothing more to offer. This action also forces the
       * decompressor to read any trailing bytes that weren't critical
       * for decompression, which is necessary to keep the stream
       * in sync.
       */
      if (input.read() >= 0 ) {
        throw new IOException("Unexpected extra bytes from input stream for " +
                               getMapId());
      }
    } finally {
      CodecPool.returnDecompressor(decompressor);
    }
  }

  @Override
  public void commit() throws IOException {
    getMerger().closeInMemoryFile(this);
  }
  
  @Override
  public void abort() {
    getMerger().unreserve(memory.length);
  }

  @Override

View on GitHub (pinned to 2add963021)

Solutions

  1. Confirm mapreduce.map.output.compress and mapreduce.map.output.compress.codec are identical for all maps of the job (set only on the job conf, never per-task).
  2. Check the source NodeManager's disk and logs for read errors on the spill file.
  3. Retry the job: transient corruption usually clears on a re-fetch or re-run of the map.
  4. If reproducible for one map output, capture the mapId/host pair and inspect the spill file on that NM.
Defensive patterns

Strategy: retry

Try / catch

catch (java.io.IOException e) { if (String.valueOf(e.getMessage()).contains("Unexpected extra bytes from input stream")) { /* corrupt map output: let the scheduler re-fetch; investigate source NM if it repeats for one mapId */ } else { throw e; } }

Prevention

When it happens

Trigger: Map output compressed with a different codec than the one used for decompression; corrupted bytes in transit; a NodeManager serving a partially overwritten or truncated spill file so the announced length no longer matches the data.

Common situations: Custom job setup code overriding mapreduce.map.output.compress / codec inconsistently across tasks of the same job; NM disk corruption; network gear mangling payloads; rare codec bugs on specific Hadoop versions.

Related errors


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