{"record":{"id":"441ae5d726366ff4","repo":"apache/hadoop","slug":"named-output-namedoutput-not-defined","errorCode":null,"errorMessage":"Named output '{namedOutput}' not defined","messagePattern":"Named output '(.+?)' not defined","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/MultipleOutputs.java","lineNumber":269,"sourceCode":"    }\n  }\n  \n  /**\n   * Checks if a named output name is valid.\n   *\n   * @param namedOutput named output Name\n   * @throws IllegalArgumentException if the output name is not valid.\n   */\n  private static void checkNamedOutputName(JobContext job,\n      String namedOutput, boolean alreadyDefined) {\n    checkTokenName(namedOutput);\n    checkBaseOutputPath(namedOutput);\n    List<String> definedChannels = getNamedOutputsList(job);\n    if (alreadyDefined && definedChannels.contains(namedOutput)) {\n      throw new IllegalArgumentException(\"Named output '\" + namedOutput +\n        \"' already alreadyDefined\");\n    } else if (!alreadyDefined && !definedChannels.contains(namedOutput)) {\n      throw new IllegalArgumentException(\"Named output '\" + namedOutput +\n        \"' not defined\");\n    }\n  }\n\n  // Returns list of channel names.\n  private static List<String> getNamedOutputsList(JobContext job) {\n    List<String> names = new ArrayList<String>();\n    StringTokenizer st = new StringTokenizer(\n      job.getConfiguration().get(MULTIPLE_OUTPUTS, \"\"), \" \");\n    while (st.hasMoreTokens()) {\n      names.add(st.nextToken());\n    }\n    return names;\n  }\n\n  // Returns the named output OutputFormat.\n  @SuppressWarnings(\"unchecked\")\n  private static Class<? extends OutputFormat<?, ?>> getNamedOutputFormatClass(","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/lib/output/MultipleOutputs.java#L251-L287","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","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"],"exampleFix":"// driver\npublic static final String CH_TEXT = \"text\";\nMultipleOutputs.addNamedOutput(job, CH_TEXT, TextOutputFormat.class, LongWritable.class, Text.class);\n\n// reducer -- before: mos.write(\"txt\", k, v);  // typo -> 'not defined'\n// reducer -- after:\nmos.write(Driver.CH_TEXT, k, v);","handlingStrategy":"validation","validationCode":"// driver-side assertion before submit\nList<String> registered = Arrays.asList(\n    conf.get(\"mapreduce.multipleoutputs\", \"\").split(\" \"));\nfor (String used : CHANNELS_USED_IN_TASKS) {\n  if (!registered.contains(used)) throw new IllegalStateException(\"Unregistered channel: \" + used);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["hadoop","mapreduce","multiple-outputs","undefined-channel","configuration","illegalargument"],"backgroundTag":"undefined-named-output","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}