{"record":{"id":"c34eea43bc6591c7","repo":"apache/hadoop","slug":"counters-are-enabled-reporter-cannot-be-null","errorCode":null,"errorMessage":"Counters are enabled, Reporter cannot be NULL","messagePattern":"Counters are enabled, Reporter cannot be NULL","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/mapred/lib/MultipleOutputs.java","lineNumber":448,"sourceCode":"   * Returns iterator with the defined name outputs.\n   *\n   * @return iterator with the defined named outputs\n   */\n  public Iterator<String> getNamedOutputs() {\n    return namedOutputs.iterator();\n  }\n\n\n  // by being synchronized MultipleOutputTask can be use with a\n  // MultithreaderMapRunner.\n  private synchronized RecordWriter getRecordWriter(String namedOutput,\n                                                    String baseFileName,\n                                                    final Reporter reporter)\n    throws IOException {\n    RecordWriter writer = recordWriters.get(baseFileName);\n    if (writer == null) {\n      if (countersEnabled && reporter == null) {\n        throw new IllegalArgumentException(\n          \"Counters are enabled, Reporter cannot be NULL\");\n      }\n      JobConf jobConf = new JobConf(conf);\n      jobConf.set(InternalFileOutputFormat.CONFIG_NAMED_OUTPUT, namedOutput);\n      FileSystem fs = FileSystem.get(conf);\n      writer =\n        outputFormat.getRecordWriter(fs, jobConf, baseFileName, reporter);\n\n      if (countersEnabled) {\n        if (reporter == null) {\n          throw new IllegalArgumentException(\n            \"Counters are enabled, Reporter cannot be NULL\");\n        }\n        writer = new RecordWriterWithCounter(writer, baseFileName, reporter);\n      }\n\n      recordWriters.put(baseFileName, writer);\n    }","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/lib/MultipleOutputs.java#L430-L466","documentation":"MultipleOutputs can optionally maintain one counter per named output (group = MultipleOutputs class name), enabled with MultipleOutputs.setCountersEnabled(conf, true) — by default counters are disabled. When a writer for a named output must be created and counters are enabled, the Reporter passed to getCollector() is needed to register/increment those counters, so getRecordWriter() throws this IllegalArgumentException if reporter is null. This is the first of two identical checks, performed before the underlying writer is created.","triggerScenarios":"MultipleOutputs.setCountersEnabled(conf, true) in the driver, then at task time a call like mos.getCollector(\"text\", null) or mos.getCollector(\"seq\", \"A\", null). Typical in unit tests or in code paths where the Reporter from map()/reduce() was not threaded through (stored in a wrapper, mocked away, or dropped when getCollector is called from a helper class).","commonSituations":"Enabling counters for the nice per-channel record counts, then reusing mapper/reducer code in a local test harness that passes null instead of a Reporter; refactoring that moves getCollector calls into helpers which don't receive the reporter parameter.","solutions":["Always pass the Reporter given to map()/reduce(): mos.getCollector(\"text\", reporter)","Thread the Reporter through helper methods that ultimately call getCollector","If no counters are needed, simply do not enable them — setCountersEnabled(conf, false) or omit the call (default is disabled)","In unit tests, pass a dummy Reporter (e.g. Reporter.NULL in the mapred API or a stub) instead of null"],"exampleFix":"// before: counters enabled but reporter dropped\nMultipleOutputs.setCountersEnabled(conf, true);\nmos.getCollector(\"text\", null).collect(key, value);\n\n// after: pass the reporter received by map()/reduce()\npublic void reduce(K key, Iterator<V> values, OutputCollector out, Reporter reporter) {\n  mos.getCollector(\"text\", reporter).collect(key, value);\n}","handlingStrategy":"validation","validationCode":"// fetch collectors through one helper that owns the reporter contract\nprivate OutputCollector collector(String name, Reporter reporter) throws IOException {\n  if (MultipleOutputs.getCountersEnabled(conf) && reporter == null) {\n    throw new IllegalStateException(\"a Reporter is required when mo.counters is enabled\");\n  }\n  return mos.getCollector(name, reporter);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Thread the Reporter from map()/reduce() into every helper that calls getCollector","Only enable counters when you can guarantee a non-null Reporter on every path","In unit tests pass Reporter.NULL (or a stub) instead of null","Create the collector once in setup and reuse it — avoids per-record null-reporter traps"],"tags":["hadoop","mapreduce","multiple-outputs","counters","reporter","null-check"],"backgroundTag":"required-parameter-null","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}