{"record":{"id":"dc41b8d2832d8905","repo":"apache/hadoop","slug":"unexpected-haservicestateproto","errorCode":null,"errorMessage":"Unexpected HAServiceStateProto:","messagePattern":"Unexpected HAServiceStateProto:","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelper.java","lineNumber":788,"sourceCode":"    if(state != null) {\n      builder.setState(convert(info.getState()));\n    }\n    return builder.build();\n  }\n\n  public static HAServiceState convert(NNHAStatusHeartbeatProto.State s) {\n    if (s == null) {\n      return null;\n    }\n    switch (s) {\n    case ACTIVE:\n      return HAServiceState.ACTIVE;\n    case STANDBY:\n      return HAServiceState.STANDBY;\n    case OBSERVER:\n      return HAServiceState.OBSERVER;\n    default:\n      throw new IllegalArgumentException(\"Unexpected HAServiceStateProto:\"\n          + s);\n    }\n  }\n\n  public static NNHAStatusHeartbeatProto.State convert(HAServiceState s) {\n    if (s == null) {\n      return null;\n    }\n    switch (s) {\n    case ACTIVE:\n      return NNHAStatusHeartbeatProto.State.ACTIVE;\n    case STANDBY:\n      return NNHAStatusHeartbeatProto.State.STANDBY;\n    case OBSERVER:\n      return NNHAStatusHeartbeatProto.State.OBSERVER;\n    default:\n      throw new IllegalArgumentException(\"Unexpected HAServiceState:\"\n          + s);","sourceCodeStart":770,"sourceCodeEnd":806,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/protocolPB/PBHelper.java#L770-L806","documentation":"Converts the state field of the NameNode HA heartbeat (NNHAStatusHeartbeatProto.State, sent from the active NN to standby/backup nodes) into HAServiceState. Only ACTIVE, STANDBY and OBSERVER are understood; any other enum value on the wire fails with IllegalArgumentException.","triggerScenarios":"A heartbeat arrives carrying a state constant this build does not know — e.g. an older standby/backup NameNode receiving a state introduced by a newer active (OBSERVER support or later additions), typically mid rolling upgrade.","commonSituations":"Mixed-version HA clusters during rolling upgrades; a standby older than the active; replaying recorded RPC traffic from a newer release in tests.","solutions":["Upgrade the node that parses the heartbeat (standby/backup NN) to at least the sender's release.","Note the unknown value from the exception message to identify the sender's version.","Finish or revert the rolling upgrade so both HA peers run the same version."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import org.apache.hadoop.ha.HAServiceState;\nimport java.util.EnumSet;\n\nstatic boolean isKnownHeartbeatState(NNHAStatusHeartbeatProto.State s) {\n  return EnumSet.of(\n      NNHAStatusHeartbeatProto.State.ACTIVE,\n      NNHAStatusHeartbeatProto.State.STANDBY,\n      NNHAStatusHeartbeatProto.State.OBSERVER).contains(s);\n}\n// guard before converting\nif (!isKnownHeartbeatState(proto.getState())) {\n  LOG.warn(\"Unknown HA heartbeat state from peer: {}\", proto.getState());\n  return;\n}","typeGuard":"static HAServiceState toHAServiceStateOrNull(NNHAStatusHeartbeatProto.State s) {\n  switch (s) {\n    case ACTIVE: return HAServiceState.ACTIVE;\n    case STANDBY: return HAServiceState.STANDBY;\n    case OBSERVER: return HAServiceState.OBSERVER;\n    default: return null; // caller skips instead of crashing\n  }\n}","tryCatchPattern":"try {\n  HAServiceState st = PBHelper.convert(proto.getState());\n} catch (IllegalArgumentException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"HAServiceStateProto\")) {\n    // peer is newer than us: log and ignore the heartbeat until upgraded\n    LOG.warn(\"Ignoring heartbeat with unknown state: {}\", e.getMessage());\n    return;\n  }\n  throw e;\n}","preventionTips":["Upgrade standby/backup NameNodes before (or together with) the active during rolling upgrades.","Treat 'Unexpected HAServiceStateProto' in logs as a hard version-skew alert.","In replay tests, regenerate recorded protos with the same release as the parser."],"tags":["hadoop","hdfs","ha","namenode","protobuf","enum"],"backgroundTag":"enum-deserialization-unknown-value","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}