apache/hadoop · error · IllegalArgumentException

Named output ' ' not defined

Error message

Named output '{}' not defined

What it means

MultipleOutputs throws this IllegalArgumentException from checkNamedOutput(conf, name, false) when a configuration-level lookup references a named output that was never registered via addNamedOutput/addMultiNamedOutput. The check backs the static getters isMultiNamedOutput(conf, name), getNamedOutputFormatClass(conf, name), getNamedOutputKeyClass and getNamedOutputValueClass — each of them first verifies the name exists in 'mo.namedOutputs'. It fires during job setup or at task time, not while writing records.

Solutions

  1. Register the name before any lookup: MultipleOutputs.addNamedOutput(conf, "channelX", formatClass, keyClass, valueClass)
  2. Define the name once as a constant and use it in both addNamedOutput and all get* calls
  3. Dump conf.get("mo.namedOutputs") to confirm which channels are actually registered before lookup

Example fix

// before: lookup without registration -> IllegalArgumentException
MultipleOutputs.getNamedOutputFormatClass(conf, "summary");

// after: register first, then query
MultipleOutputs.addNamedOutput(conf, "summary", TextOutputFormat.class, Text.class, Text.class);
Class<? extends OutputFormat> fmt = MultipleOutputs.getNamedOutputFormatClass(conf, "summary");
Defensive patterns

Strategy: validation

Validate before calling

// verify registration before any static lookup
if (!MultipleOutputs.getNamedOutputsList(conf).contains(name)) {
  throw new IllegalArgumentException("named output not registered: " + name);
}
Class<? extends OutputFormat> f = MultipleOutputs.getNamedOutputFormatClass(conf, name);

Prevention

When it happens

Trigger: Calling MultipleOutputs.getNamedOutputFormatClass(conf, "channelX", ...) or isMultiNamedOutput(conf, "channelX") for a name that has no addNamedOutput(conf, "channelX", ...) call anywhere. Also reached indirectly: the task-side InternalFileOutputFormat.getRecordWriter resolves the configured named output's format class, so a JobConf that carries mo.config.namedOutput but lost the mo.namedOutputs/mo.namedOutput.* entries fails here.

Common situations: Driver and task code drifting out of sync after a rename of a named output; JobConf built in one place and stripped/serialized in another (XML round-trip dropping keys); typos between registration and lookup strings.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/955df0d67b1115d9. Report an issue: GitHub.

Appendix: source

Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/lib/MultipleOutputs.java:179

  /**
   * Checks if a named output is alreadyDefined or not.
   *
   * @param conf           job conf
   * @param namedOutput    named output names
   * @param alreadyDefined whether the existence/non-existence of
   *                       the named output is to be checked
   * @throws IllegalArgumentException if the output name is alreadyDefined or
   *                                  not depending on the value of the
   *                                  'alreadyDefined' parameter
   */
  private static void checkNamedOutput(JobConf conf, String namedOutput,
                                       boolean alreadyDefined) {
    List<String> definedChannels = getNamedOutputsList(conf);
    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");
    }
  }

  /**
   * Checks if a named output name is valid token.
   *
   * @param namedOutput named output Name
   * @throws IllegalArgumentException if the output name is not valid.
   */
  private static void checkTokenName(String namedOutput) {
    if (namedOutput == null || namedOutput.length() == 0) {
      throw new IllegalArgumentException(
        "Name cannot be NULL or emtpy");
    }
    for (char ch : namedOutput.toCharArray()) {
      if ((ch >= 'A') && (ch <= 'Z')) {
        continue;

View on GitHub (pinned to 2add963021)