apache/hadoop · error · UnsupportedOperationException

Input only available on map

Error message

Input only available on map

What it means

In the old MapReduce API, Task.ReporterImpl can carry the job's InputSplit, but the split is only set for map tasks. getInputSplit() throws UnsupportedOperationException when the split field is null — i.e. whenever it is called from a reduce task or before the split was injected. This is the reduce-phase counterpart of the map-only input-split contract.

Source

Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/Task.java:741

      if(skipping && SkipBadRecords.COUNTER_GROUP.equals(group) && (
          SkipBadRecords.COUNTER_MAP_PROCESSED_RECORDS.equals(counter) ||
          SkipBadRecords.COUNTER_REDUCE_PROCESSED_GROUPS.equals(counter))) {
        //if application reports the processed records, move the 
        //currentRecStartIndex to the next.
        //currentRecStartIndex is the start index which has not yet been 
        //finished and is still in task's stomach.
        for(int i=0;i<amount;i++) {
          currentRecStartIndex = currentRecIndexIterator.next();
        }
      }
      setProgressFlag();
    }
    public void setInputSplit(InputSplit split) {
      this.split = split;
    }
    public InputSplit getInputSplit() throws UnsupportedOperationException {
      if (split == null) {
        throw new UnsupportedOperationException("Input only available on map");
      } else {
        return split;
      }
    }

    /**
     * exception thrown when the task exceeds some configured limits.
     */
    public class TaskLimitException extends IOException {
      public TaskLimitException(String str) {
        super(str);
      }
    }

    /**
     * disk limit checker, runs in separate thread when activated.
     */
    public class DiskLimitCheck implements Runnable {

View on GitHub (pinned to 2add963021)

Solutions

  1. Call reporter.getInputSplit() only in map-side code; guard with the task's isMapTask() or conf.getUseNewMapper()/job context.
  2. Pass input metadata (file name, offset) to the reducer via job configuration or the key/value data instead.
  3. In the new API use Context.getInputSplit() inside Mapper.map(), where it is always available.

Example fix

// before
String file = ((FileSplit) reporter.getInputSplit()).getPath().getName();

// after
if (isMapPhase) { // e.g. flagged via job conf
  String file = ((FileSplit) reporter.getInputSplit()).getPath().getName();
}
Defensive patterns

Strategy: type-guard

Type guard

static boolean taskHasInputSplit(Reporter r) {
  return r != null && r != Reporter.NULL && taskIsMap(conf);
}
// inside map(): safe; inside reduce()/cleanup(): never call reporter.getInputSplit()

Prevention

When it happens

Trigger: Calling reporter.getInputSplit() inside reduce(...) or setup(...) of a job whose reduce side receives the same reporter; generic mapper/reducer utilities that query the split regardless of task type; custom InputFormat wiring that forgets reporter.setInputSplit(split).

Common situations: Shared setup() code that reads the FileSplit to get the input file name, reused across map and reduce classes; migrating old-API jobs where reduce-side code accidentally inherits map-side logic.

Related errors


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