{"record":{"id":"9a4f369ae0d973e4","repo":"apache/hadoop","slug":"getmapfinishtime-not-supported-for-reducetask","errorCode":null,"errorMessage":"getMapFinishTime() not supported for ReduceTask","messagePattern":"getMapFinishTime\\(\\) 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":92,"sourceCode":"    this.shuffleFinishTime = shuffleFinishTime;\n  }\n\n  @Override\n  public long getSortFinishTime() {\n    return sortFinishTime;\n  }\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  }","sourceCodeStart":74,"sourceCodeEnd":110,"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#L74-L110","documentation":"ReduceTaskStatus tracks shuffle-finish, sort-finish, and finish times for reduce attempts; a map finish time simply does not exist for reduces. The override of getMapFinishTime() therefore always throws UnsupportedOperationException, mirroring setMapFinishTime(). Code that walks mixed TaskStatus objects and unconditionally reads map timings will blow up on every reduce status.","triggerScenarios":"Calling status.getMapFinishTime() on a TaskStatus whose getIsMap() is false, e.g. generic task-duration tooling, JMX/history serializers, or monitoring code shared between map and reduce paths.","commonSituations":"Job-history analyzers and dashboards that assume all task statuses expose map finish time; code copied from map-side diagnostics into a reduce path.","solutions":["Branch on status.getIsMap() before calling getMapFinishTime().","For reduce tasks use getShuffleFinishTime(), getSortFinishTime(), and getFinishTime() instead.","Search the codebase for getMapFinishTime() call sites that run inside loops over all task statuses and guard each one."],"exampleFix":"// before\nlong mapDone = status.getMapFinishTime();\n\n// after\nlong mapDone = status.getIsMap() ? status.getMapFinishTime() : -1L;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean hasMapFinishTime(TaskStatus s) {\n  return s != null && s.getIsMap();\n}","tryCatchPattern":null,"preventionTips":["Branch on TaskStatus.getIsMap() before touching map-only fields.","For reduces, expose shuffle/sort/finish times instead of a map finish time.","In shared monitoring code, wrap status field reads behind accessors that check task type."],"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"}