{"record":{"id":"9b5a4c909e350a94","repo":"apache/hadoop","slug":"getshufflefinishtime-not-supported-for-maptask","errorCode":null,"errorMessage":"getShuffleFinishTime() not supported for MapTask","messagePattern":"getShuffleFinishTime\\(\\) not supported for MapTask","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/MapTaskStatus.java","lineNumber":59,"sourceCode":"    return true;\n  }\n\n  /**\n   * Sets finishTime. \n   * @param finishTime finish time of task.\n   */\n  @Override\n  void setFinishTime(long finishTime) {\n    super.setFinishTime(finishTime);\n    // set mapFinishTime if it hasn't been set before\n    if (getMapFinishTime() == 0) {\n      setMapFinishTime(finishTime);\n    }\n  }\n  \n  @Override\n  public long getShuffleFinishTime() {\n    throw new UnsupportedOperationException(\"getShuffleFinishTime() not supported for MapTask\");\n  }\n\n  @Override\n  void setShuffleFinishTime(long shuffleFinishTime) {\n    throw new UnsupportedOperationException(\"setShuffleFinishTime() not supported for MapTask\");\n  }\n\n  @Override\n  public long getMapFinishTime() {\n    return mapFinishTime;\n  }\n  \n  @Override\n  void setMapFinishTime(long mapFinishTime) {\n    this.mapFinishTime = mapFinishTime;\n  }\n  \n  @Override","sourceCodeStart":41,"sourceCodeEnd":77,"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/MapTaskStatus.java#L41-L77","documentation":"MapTaskStatus models only map-phase timing (mapFinishTime); shuffle and sort finish times exist solely on ReduceTaskStatus because maps never shuffle input. Calling getShuffleFinishTime() on a map task's status throws UnsupportedOperationException by design.","triggerScenarios":"Generic code iterating task reports calls status.getShuffleFinishTime() without checking task type: monitoring/audit dashboards, JSON/JMX serializers that walk all getters, or code ported from paths that only ever saw ReduceTaskStatus.","commonSituations":"Custom job-history or monitoring tooling reading timings from every task; reflection-based serializers touching reduce-only getters; libraries shared between map and reduce handling paths.","solutions":["Branch on task type first: status.getIsMap() (or instanceof ReduceTaskStatus) before calling shuffle APIs","Use getMapFinishTime() for maps and getShuffleFinishTime()/getSortFinishTime() only for reduces","Teach serializers to skip reduce-only getters for map tasks (view/annotation-based exclusion)"],"exampleFix":"// before\nlong phaseEnd = status.getShuffleFinishTime(); // throws for map attempts\n\n// after\nlong phaseEnd = status.getIsMap()\n    ? status.getMapFinishTime()\n    : status.getShuffleFinishTime();","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean hasShuffleFinishTime(TaskStatus s) {\n  return s != null && !s.getIsMap(); // equivalently: s instanceof ReduceTaskStatus\n}","tryCatchPattern":"if (hasShuffleFinishTime(status)) { shuffleEnd = status.getShuffleFinishTime(); } else { mapEnd = status.getMapFinishTime(); } // guard first; only catch UnsupportedOperationException as a last-resort signal of a type bug","preventionTips":["Model task phases by task type: map -> mapFinish, reduce -> shuffle/sort/finish","Never call reduce-only TaskStatus methods from generic code paths","Write one adapter (getPhaseFinishTime(TaskStatus)) and use it everywhere"],"tags":["hadoop","mapreduce","taskstatus","unsupported-operation","api-misuse"],"backgroundTag":"unsupported-operation","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}