apache/hadoop · error · IOException

Type mismatch in key from map: expected {keyClassName}, rece

Error message

Type mismatch in key from map: expected {keyClassName}, received {actualKeyClassName}

What it means

The sorting collector type-checks every key passed to OutputCollector.collect() / Context.write() with an exact getClass() comparison against the configured map-output key class (mapreduce.map.output.key.class, set via Job.setMapOutputKeyClass). When map() emits a key of a different runtime class - including a subclass - the map task fails with this IOException on the first offending record.

Source

Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/MapTask.java:1097

      } finally {
        spillLock.unlock();
      }
      if (sortSpillException != null) {
        throw new IOException("Spill thread failed to initialize",
            sortSpillException);
      }
    }

    /**
     * Serialize the key, value to intermediate storage.
     * When this method returns, kvindex must refer to sufficient unused
     * storage to store one METADATA.
     */
    public synchronized void collect(K key, V value, final int partition
                                     ) throws IOException {
      reporter.progress();
      if (key.getClass() != keyClass) {
        throw new IOException("Type mismatch in key from map: expected "
                              + keyClass.getName() + ", received "
                              + key.getClass().getName());
      }
      if (value.getClass() != valClass) {
        throw new IOException("Type mismatch in value from map: expected "
                              + valClass.getName() + ", received "
                              + value.getClass().getName());
      }
      if (partition < 0 || partition >= partitions) {
        throw new IOException("Illegal partition for " + key + " (" +
            partition + ")");
      }
      checkSpillException();
      bufferRemaining -= METASIZE;
      if (bufferRemaining <= 0) {
        // start spill if the thread is not running and the soft limit has been
        // reached
        spillLock.lock();

View on GitHub (pinned to 2add963021)

Solutions

  1. Call job.setMapOutputKeyClass(...) with exactly the class map() writes (and setMapOutputValueClass for the value)
  2. Check the Mapper<K,V,K2,V2> generic signature and every context.write(...) in map() and cleanup()
  3. If a combiner is configured, its input key type must match the map output key type - verify or remove it
  4. Smoke-test with LocalJobRunner or a mapper unit test before cluster submission

Example fix

// before
public class UpperMapper extends Mapper<LongWritable, Text, Text, Text> { /* writes Text keys */ }
job.setOutputKeyClass(Text.class);          // only final output classes set
job.setOutputValueClass(Text.class);

// after
job.setMapOutputKeyClass(Text.class);       // what the mapper emits
job.setMapOutputValueClass(Text.class);
job.setOutputKeyClass(Text.class);          // what the reducer emits
job.setOutputValueClass(Text.class);
Defensive patterns

Strategy: validation

Validate before calling

// before job.submit(): mapper's generic K2/V2 must equal configured map-output classes
Type t = TokenMapper.class.getGenericSuperclass();
if (t instanceof ParameterizedType) {
  Type[] a = ((ParameterizedType) t).getActualTypeArguments();
  if (!job.getMapOutputKeyClass().equals(a[2]) || !job.getMapOutputValueClass().equals(a[3])) {
    throw new IllegalStateException("Mapper emits " + a[2] + "," + a[3]
        + " but job configured " + job.getMapOutputKeyClass() + "," + job.getMapOutputValueClass());
  }
}

Prevention

When it happens

Trigger: Mapper emits key instances whose class differs from job.getMapOutputKeyClass(); the job never called setMapOutputKeyClass so it defaults to the final output key class while the mapper writes something else; old-API JobConf with a wrong mapred.mapoutput.keyclass value.

Common situations: Mapper generics edited without updating job setup; mapper emits Text while the input format's LongWritable key is still the default; chained mappers/combiners with different schemas; jobs ported between old and new APIs where output types changed.

Related errors


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