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
- Call job.setMapOutputKeyClass(...) with exactly the class map() writes (and setMapOutputValueClass for the value)
- Check the Mapper<K,V,K2,V2> generic signature and every context.write(...) in map() and cleanup()
- If a combiner is configured, its input key type must match the map output key type - verify or remove it
- 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
- Always set map-output key/value classes whenever they differ from the final output classes
- Keep mapper generic parameters in sync with the classes actually constructed at emit sites
- Run a one-record local integration test of each new mapper before cluster submission
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
- Type mismatch in value from map: expected {valueClassName},
- absolutePath + " is a file"
- f.toString()
- input array component type {} does not match declared type {
- Could not find a serializer for the Key class: '{}'. Please
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/a1bd3f6e7ef37e4d.
Report an issue: GitHub.