apache/hadoop · error · IllegalArgumentException
Named output '{namedOutput}' not defined
Error message
Named output '{namedOutput}' not defined What it means
Thrown as IllegalArgumentException from MultipleOutputs.checkNamedOutputName (MultipleOutputs.java:269) when a name is used for writing but is NOT in the mapreduce.multipleoutputs list of the Configuration visible to the running context. It is the inverse check of the duplicate guard: write() demands alreadyDefined==false channels to exist. Root cause is always a registration/config-visibility mismatch.
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/MultipleOutputs.java:269
}
}
/**
* Checks if a named output name is valid.
*
* @param namedOutput named output Name
* @throws IllegalArgumentException if the output name is not valid.
*/
private static void checkNamedOutputName(JobContext job,
String namedOutput, boolean alreadyDefined) {
checkTokenName(namedOutput);
checkBaseOutputPath(namedOutput);
List<String> definedChannels = getNamedOutputsList(job);
if (alreadyDefined && definedChannels.contains(namedOutput)) {
throw new IllegalArgumentException("Named output '" + namedOutput +
"' already alreadyDefined");
} else if (!alreadyDefined && !definedChannels.contains(namedOutput)) {
throw new IllegalArgumentException("Named output '" + namedOutput +
"' not defined");
}
}
// Returns list of channel names.
private static List<String> getNamedOutputsList(JobContext job) {
List<String> names = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(
job.getConfiguration().get(MULTIPLE_OUTPUTS, ""), " ");
while (st.hasMoreTokens()) {
names.add(st.nextToken());
}
return names;
}
// Returns the named output OutputFormat.
@SuppressWarnings("unchecked")
private static Class<? extends OutputFormat<?, ?>> getNamedOutputFormatClass(View on GitHub (pinned to 2add963021)
Solutions
- Align the names: define channel names as public static final String constants used by both the driver's addNamedOutput and the task's mos.write
- Ensure addNamedOutput runs on the Job's Configuration BEFORE job.submit()/waitForCompletion()
- Verify the key arrives in tasks: dump conf.get("mapreduce.multipleoutputs") in the Mapper's setup() and compare with the driver
Example fix
// driver
public static final String CH_TEXT = "text";
MultipleOutputs.addNamedOutput(job, CH_TEXT, TextOutputFormat.class, LongWritable.class, Text.class);
// reducer -- before: mos.write("txt", k, v); // typo -> 'not defined'
// reducer -- after:
mos.write(Driver.CH_TEXT, k, v); Defensive patterns
Strategy: validation
Validate before calling
// driver-side assertion before submit
List<String> registered = Arrays.asList(
conf.get("mapreduce.multipleoutputs", "").split(" "));
for (String used : CHANNELS_USED_IN_TASKS) {
if (!registered.contains(used)) throw new IllegalStateException("Unregistered channel: " + used);
} Prevention
- Share channel-name constants between driver and task code
- Call addNamedOutput before job.submit()
- Verify conf propagation by dumping mapreduce.multipleoutputs in Mapper.setup() during debugging
When it happens
Trigger: mos.write("txt", k, v) in a Mapper/Reducer while the job only registered 'text' (typo/case mismatch); addNamedOutput called on a DIFFERENT Job/Configuration than the one the task sees (e.g. registered after job submission, on a copy, or on the client's conf while tasks deserialize a conf snapshot taken earlier); conf whitelisting stripped mapreduce.multipleoutputs.namedOutput.* keys.
Common situations: Name typos between driver and reducer code; calling addNamedOutput after job.submit(); frameworks (Tez, Spark-Hadoop bridges, custom runners) that filter which conf keys reach the task; case-sensitive 'Text' vs 'text'.
Related errors
- Named output '{namedOutput}' already alreadyDefined
- Undefined named output '{namedOutput}'
- Named output '{}' already alreadyDefined
- Named output '{}' not defined
- Name cannot be NULL or emtpy
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/441ae5d726366ff4.
Report an issue: GitHub.