{"record":{"id":"e22f16b6d48ffb9c","repo":"apache/hadoop","slug":"setmapfinishtime-not-supported-for-reducetask","errorCode":null,"errorMessage":"setMapFinishTime() not supported for ReduceTask","messagePattern":"setMapFinishTime\\(\\) not supported for ReduceTask","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/ReduceTaskStatus.java","lineNumber":98,"sourceCode":"  }\n\n  @Override\n  void setSortFinishTime(long sortFinishTime) {\n    this.sortFinishTime = sortFinishTime;\n    if (0 == this.shuffleFinishTime){\n      this.shuffleFinishTime = sortFinishTime;\n    }\n  }\n\n  @Override\n  public long getMapFinishTime() {\n    throw new UnsupportedOperationException(\n        \"getMapFinishTime() not supported for ReduceTask\");\n  }\n\n  @Override\n  void setMapFinishTime(long shuffleFinishTime) {\n    throw new UnsupportedOperationException(\n        \"setMapFinishTime() not supported for ReduceTask\");\n  }\n\n  @Override\n  public List<TaskAttemptID> getFetchFailedMaps() {\n    return failedFetchTasks;\n  }\n  \n  @Override\n  public void addFetchFailedMap(TaskAttemptID mapTaskId) {\n    failedFetchTasks.add(mapTaskId);\n  }\n  \n  @Override\n  synchronized void statusUpdate(TaskStatus status) {\n    super.statusUpdate(status);\n    \n    if (status.getShuffleFinishTime() != 0) {","sourceCodeStart":80,"sourceCodeEnd":116,"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/ReduceTaskStatus.java#L80-L116","documentation":"ReduceTaskStatus does not accept a map finish time; setMapFinishTime() always throws UnsupportedOperationException (the parameter name shuffleFinishTime is a leftover — the value is never stored). Only MapTaskStatus implements this setter. It is invoked by framework code that updates timings when a phase completes, so calling it on reduce statuses is always a bug in the caller.","triggerScenarios":"Calling status.setMapFinishTime(t) on a reduce attempt's status, e.g. shared progress-update code, custom TaskAttemptListeners, or deserialization hooks that replay map events onto reduce statuses.","commonSituations":"Porting map-side bookkeeping to a code path that also handles reduces; mock/fake status objects in tests replaced by real ReduceTaskStatus; MR1-to-MR2 migration code that copies status fields generically.","solutions":["Guard the call with status.getIsMap() before setting map finish time.","For reduce timings use setShuffleFinishTime() / setSortFinishTime() / setFinishTime().","Audit generic copy methods (for example status-merging helpers) for unconditional setMapFinishTime calls."],"exampleFix":"// before\nstatus.setMapFinishTime(ts);\n\n// after\nif (status.getIsMap()) {\n  status.setMapFinishTime(ts);\n} else {\n  status.setFinishTime(ts);\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean acceptsMapFinishTime(TaskStatus s) {\n  return s != null && s.getIsMap();\n}","tryCatchPattern":null,"preventionTips":["Never copy status fields generically; branch on getIsMap().","Prefer framework entry points that set timings automatically on phase completion.","In tests, use MapTaskStatus when exercising setMapFinishTime."],"tags":["hadoop","mapreduce","task-status","unsupported-operation","reduce"],"backgroundTag":"unsupported-operation-on-type","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}