apache/hadoop · error · IllegalStateException
A Mapper can be added to the chain only after the Reducer ha
Error message
A Mapper can be added to the chain only after the Reducer has been set
What it means
ChainReducer composes map-reduce-map pipelines; the reducer must be registered before any reducer-side mapper. checkReducerAlreadySet(shouldSet=true) throws IllegalStateException("A Mapper can be added to the chain only after the Reducer has been set") when ChainReducer.addMapper(...) is called while the 'chain reducer class' key is absent from the job configuration, i.e. ChainReducer.setReducer(...) has not been invoked yet.
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/chain/Chain.java:655
// set the mapper class
int index = getIndex(jobConf, prefix);
jobConf.setClass(prefix + CHAIN_MAPPER_CLASS + index, klass, Mapper.class);
validateKeyValueTypes(isMap, jobConf, inputKeyClass, inputValueClass,
outputKeyClass, outputValueClass, index, prefix);
setMapperConf(isMap, jobConf, inputKeyClass, inputValueClass,
outputKeyClass, outputValueClass, mapperConf, index, prefix);
}
// if a reducer chain check the Reducer has been already set or not
protected static void checkReducerAlreadySet(boolean isMap,
Configuration jobConf, String prefix, boolean shouldSet) {
if (!isMap) {
if (shouldSet) {
if (jobConf.getClass(prefix + CHAIN_REDUCER_CLASS, null) == null) {
throw new IllegalStateException(
"A Mapper can be added to the chain only after the Reducer has "
+ "been set");
}
} else {
if (jobConf.getClass(prefix + CHAIN_REDUCER_CLASS, null) != null) {
throw new IllegalStateException("Reducer has been already set");
}
}
}
}
protected static void validateKeyValueTypes(boolean isMap,
Configuration jobConf, Class<?> inputKeyClass, Class<?> inputValueClass,
Class<?> outputKeyClass, Class<?> outputValueClass, int index,
String prefix) {
// if it is a reducer chain and the first Mapper is being added check the
// key and value input classes of the mapper match those of the reducer
// output.View on GitHub (pinned to 2add963021)
Solutions
- Call ChainReducer.setReducer(job, Reducer.class, inK, inV, outK, outV, byValue) first, then every ChainReducer.addMapper(...), then submit.
- Centralize the wiring order in one builder method so call order cannot regress.
- Ensure setReducer's class/key/value arguments are non-null so registration actually stores the reducer.
Example fix
// before
ChainReducer.addMapper(job, CleanupMapper.class,
Text.class, Text.class, Text.class, Text.class, false); // IllegalStateException
ChainReducer.setReducer(job, Reduce.class,
LongWritable.class, Text.class, Text.class, Text.class, false);
// after
ChainReducer.setReducer(job, Reduce.class,
LongWritable.class, Text.class, Text.class, Text.class, false);
ChainReducer.addMapper(job, CleanupMapper.class,
Text.class, Text.class, Text.class, Text.class, false); Defensive patterns
Strategy: validation
Validate before calling
// enforce ordering in one builder method
static void wireChain(Job job) {
ChainReducer.setReducer(job, Reduce.class,
LongWritable.class, Text.class, Text.class, IntWritable.class, false);
ChainReducer.addMapper(job, PostMap.class,
Text.class, IntWritable.class, Text.class, Text.class, false);
} Prevention
- Always call ChainReducer.setReducer before any ChainReducer.addMapper on the same job.
- Keep chain wiring in a single method so ordering cannot be broken by refactors.
- Smoke-test job assembly in CI by wiring the chain against a test Configuration.
When it happens
Trigger: Calling ChainReducer.addMapper(job, ...) before ChainReducer.setReducer(job, ...) on the same Job/Configuration; or setReducer arguments (e.g. reducerClass) wrong so the class key was never stored. Only applies to the reducer-side chain (!isMap); ChainMapper has no such ordering rule.
Common situations: Refactors reordering builder calls; adapting a ChainMapper example into a ChainReducer flow; copying job-assembly code that sets the mapper chain first out of habit.
Related errors
- Reducer has been already set
- The Reducer output key class does not match the Mapper input
- Unable to recover task %s, output: %s
- Shutdown in progress, cannot add a shutdownHook
- Shutdown in progress, cannot remove a shutdownHook
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/1ecd30ed66da7db0.
Report an issue: GitHub.