{"record":{"id":"fbd0821ff0c3f943","repo":"apache/hadoop","slug":"unexpected-counter-group-type-grouptype","errorCode":null,"errorMessage":"Unexpected counter group type: ${groupType}","messagePattern":"Unexpected counter group type: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/counters/AbstractCounters.java","lineNumber":305,"sourceCode":"    if (version != groupFactory.version()) {\n      throw new IOException(\"Counters version mismatch, expected \"+\n          groupFactory.version() +\" got \"+ version);\n    }\n    int numFGroups = WritableUtils.readVInt(in);\n    fgroups.clear();\n    GroupType[] groupTypes = GroupType.values();\n    while (numFGroups-- > 0) {\n      GroupType groupType = groupTypes[WritableUtils.readVInt(in)];\n      G group;\n      switch (groupType) {\n        case FILESYSTEM: // with nothing\n          group = groupFactory.newFileSystemGroup();\n          break;\n        case FRAMEWORK:  // with group id\n          group = groupFactory.newFrameworkGroup(WritableUtils.readVInt(in));\n          break;\n        default: // Silence dumb compiler, as it would've thrown earlier\n          throw new IOException(\"Unexpected counter group type: \"+ groupType);\n      }\n      group.readFields(in);\n      fgroups.put(group.getName(), group);\n    }\n    int numGroups = WritableUtils.readVInt(in);\n    while (numGroups-- > 0) {\n      limits.checkGroups(groups.size() + 1);\n      G group = groupFactory.newGenericGroup(\n          StringInterner.weakIntern(Text.readString(in)), null, limits);\n      group.readFields(in);\n      groups.put(group.getName(), group);\n    }\n  }\n\n  /**\n   * Return textual representation of the counter values.\n   * @return the string\n   */","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/counters/AbstractCounters.java#L287-L323","documentation":"While deserializing the framework counter groups, AbstractCounters.readFields switches over the GroupType enum (FILESYSTEM, FRAMEWORK). The 'default' branch throwing IOException(\"Unexpected counter group type\") is a defensive guard for an enum constant the switch does not handle; with the current two-constant enum it is effectively unreachable because the group type is read as an in-range index into GroupType.values(). It fires only when the enum and the switch fall out of sync (a fork adds a GroupType without a case) or the stream is corrupted/misaligned.","triggerScenarios":"Deserializing a counters stream written by a patched Hadoop that added a GroupType constant not handled by this switch; or a corrupted/misaligned stream that decodes to an unhandled switch path. Stock Hadoop cannot produce this from a well-formed stream.","commonSituations":"Forked Hadoop builds that extend the counters framework; counters payloads corrupted in transit or truncated then misread; cross-version deserialization after the enum layout changed.","solutions":["If you maintain a Hadoop fork, handle every GroupType constant in the readFields switch (map the new constant to a factory method).","Rebuild both producer and consumer from the same source so the enum and switch stay in sync.","Treat the counters as lost on corruption: discard the stream and rebuild counters from task reports instead of replaying bytes."],"exampleFix":"// fork patch pattern: keep switch exhaustive over GroupType\nswitch (groupType) {\n  case FILESYSTEM:\n    group = groupFactory.newFileSystemGroup();\n    break;\n  case FRAMEWORK:\n    group = groupFactory.newFrameworkGroup(WritableUtils.readVInt(in));\n    break;\n  case MY_NEW_TYPE: // added constant must be handled here too\n    group = groupFactory.newMyNewGroup(WritableUtils.readVInt(in));\n    break;\n  default:\n    throw new IOException(\"Unexpected counter group type: \" + groupType);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (IOException e) when deserializing counters: log the stream source, fall back to empty Counters, and continue - the payload is unreadable and retrying the same bytes cannot succeed.","preventionTips":["In forks, keep the GroupType switch in readFields exhaustive and covered by a serialization round-trip unit test over GroupType.values().","Do not hand-edit or partially rewrite serialized counters blobs."],"tags":["hadoop","mapreduce","counters","deserialization","defensive","ioexception"],"backgroundTag":"unhandled-enum-value","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}