apache/hadoop · error · IllegalArgumentException
Undefined named output '{namedOutput}'
Error message
Undefined named output '{namedOutput}' What it means
Thrown as IllegalArgumentException from MultipleOutputs.write (MultipleOutputs.java:450). Unlike the sibling 'not defined' check (which reads the Configuration live), this guard checks the instance-level set namedOutputs, snapshotted once in the MultipleOutputs constructor from the context configuration. It fires when the name passes the config check but is missing from that snapshot — i.e. the Configuration was mutated to add the named output AFTER the MultipleOutputs instance was created.
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/MultipleOutputs.java:450
* Write key and value to baseOutputPath using the namedOutput.
*
* @param namedOutput the named output name
* @param key the key
* @param value the value
* @param baseOutputPath base-output path to write the record to.
* Note: Framework will generate unique filename for the baseOutputPath
* <b>Warning</b>: when the baseOutputPath is a path that resolves
* outside of the final job output directory, the directory is created
* immediately and then persists through subsequent task retries, breaking
* the concept of output committing.
*/
@SuppressWarnings("unchecked")
public <K, V> void write(String namedOutput, K key, V value,
String baseOutputPath) throws IOException, InterruptedException {
checkNamedOutputName(context, namedOutput, false);
checkBaseOutputPath(baseOutputPath);
if (!namedOutputs.contains(namedOutput)) {
throw new IllegalArgumentException("Undefined named output '" +
namedOutput + "'");
}
TaskAttemptContext taskContext = getContext(namedOutput);
getRecordWriter(taskContext, baseOutputPath).write(key, value);
}
/**
* Write key value to an output file name.
*
* Gets the record writer from job's output format.
* Job's output format should be a FileOutputFormat.
*
* @param key the key
* @param value the value
* @param baseOutputPath base-output path to write the record to.
* Note: Framework will generate unique filename for the baseOutputPath
* <b>Warning</b>: when the baseOutputPath is a path that resolves
* outside of the final job output directory, the directory is createdView on GitHub (pinned to 2add963021)
Solutions
- Do all addNamedOutput calls at job-setup time, before any MultipleOutputs instance is constructed in setup()
- Construct MultipleOutputs fresh (in Mapper/Reducer setup) after all registration is complete; never add channels mid-task
- In tests, build the Job conf fully first, then new MultipleOutputs(new TaskAttemptContextImpl(conf, attemptId))
Example fix
// before (test / shared-conf scenario)
MultipleOutputs<Text, Text> mos = new MultipleOutputs<>(context);
MultipleOutputs.addNamedOutput(job, "late", TextOutputFormat.class, ...); // after snapshot
mos.write("late", k, v); // config has it, instance set does not -> throws
// after
MultipleOutputs.addNamedOutput(job, "late", TextOutputFormat.class, ...);
MultipleOutputs<Text, Text> mos = new MultipleOutputs<>(context); // snapshot includes 'late'
mos.write("late", k, v); Defensive patterns
Strategy: validation
Validate before calling
// construct MOS only after registration is complete
// driver: all addNamedOutput(...) calls first, then submit
// task setup:
protected void setup(Context context) {
mos = new MultipleOutputs<>(context); // snapshot now includes every channel
} Prevention
- Never call addNamedOutput after creating a MultipleOutputs instance
- In tests, finalize the Job conf before building the MOS
- Treat task conf as immutable at runtime
When it happens
Trigger: In task code (usually unit tests or embedded/local runners that share one Configuration object): construct new MultipleOutputs(context), then call addNamedOutput(jobUsingSameConf, name, ...) (or otherwise set mapreduce.multipleoutputs), then mos.write(name, ...) — the config now contains the channel, but the instance set does not. In normal cluster runs the task conf is immutable, so the earlier 'not defined' error (4337) is what you hit instead.
Common situations: Unit tests driving MultipleOutputs directly with a shared Configuration; helper libraries that lazily register channels during reduce(); MRLocalJobRunner-based tests where driver and task share conf state in one JVM.
Related errors
- Named output '{namedOutput}' not defined
- Name cannot be NULL or emtpy
- Name cannot be have a '{ch}' char
- output name cannot be 'part'
- Named output '{namedOutput}' already alreadyDefined
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/15f973b385fabf05.
Report an issue: GitHub.