{"record":{"id":"55d73f34538cf0fd","repo":"apache/hadoop","slug":"transition-from-state-to-is-not-allowed","errorCode":null,"errorMessage":"Transition from state {} to {} is not allowed.","messagePattern":"Transition from state (.+?) to (.+?) is not allowed\\.","errorType":"exception","errorClass":"ServiceFailedException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/HAState.java","lineNumber":140,"sourceCode":"   * Method to be overridden by subclasses to perform steps necessary for\n   * exiting a state.\n   * @param context HA context\n   * @throws ServiceFailedException on failure to enter the state.\n   */\n  public abstract void exitState(final HAContext context)\n      throws ServiceFailedException;\n\n  /**\n   * Move from the existing state to a new state\n   * @param context HA context\n   * @param s new state\n   * @throws ServiceFailedException on failure to transition to new state.\n   */\n  public void setState(HAContext context, HAState s) throws ServiceFailedException {\n    if (this == s) { // Already in the new state\n      return;\n    }\n    throw new ServiceFailedException(\"Transition from state \" + this + \" to \"\n        + s + \" is not allowed.\");\n  }\n  \n  /**\n   * Check if an operation is supported in a given state.\n   * @param context HA context\n   * @param op Type of the operation.\n   * @throws StandbyException if a given type of operation is not\n   *           supported in standby state\n   */\n  public abstract void checkOperation(final HAContext context, final OperationCategory op)\n      throws StandbyException;\n\n  public abstract boolean shouldPopulateReplQueues();\n\n  /**\n   * @return String representation of the service state.\n   */","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/HAState.java#L122-L158","documentation":"HAState is the base of the NameNode HA state machine. Only specific transitions are legal: ActiveState permits only Active->Standby; StandbyState permits Standby->Active and Standby->Observer; an observer (StandbyState with isObserver=true) permits Observer->Standby. The base HAState.setState() throws ServiceFailedException for every other from/to pair, so any transition not modelled by a subclass override is rejected.","triggerScenarios":"Requesting a transition the current state cannot perform in one step, typically ACTIVE -> OBSERVER directly ('hdfs haadmin -transitionToObserver' on an active NN) instead of via STANDBY; also custom tooling calling HAServiceProtocol.transitionToStandby/Active/Observer in a sequence the state machine does not allow.","commonSituations":"Manual failover drills whose haadmin commands are chained in the wrong order; runbooks written before observer support that now target observers; ZKFC racing a manual transition; admin scripts assuming any-to-any transitions are legal.","solutions":["Route multi-step changes through standby: run -transitionToStandby first, confirm with 'hdfs haadmin -getServiceState', then -transitionToObserver (or -transitionToActive)","Always read the current state before requesting a transition instead of assuming it","If automatic failover is enabled, stop the target NN's ZKFC before manual transitions to avoid racing state changes","In code, call transitionTo* on the target NN and on ServiceFailedException re-read HAServiceState before re-planning the path"],"exampleFix":"# before: active -> observer in one step (rejected)\nhdfs haadmin -transitionToObserver nn2\n# after: two legal steps\nhdfs haadmin -transitionToStandby nn2\nhdfs haadmin -getServiceState nn2   # must print standby\nhdfs haadmin -transitionToObserver nn2","handlingStrategy":"try-catch","validationCode":"// Read actual state before planning a transition\nHAServiceProtocol proxy = HAUtil.getProxiesForAllNNs... // or your resolved proxy\nHAServiceState cur = proxy.getServiceStatus().getState();\nif (cur == HAServiceState.ACTIVE && target == HAServiceState.OBSERVER) {\n  // plan two steps: ACTIVE -> STANDBY -> OBSERVER\n}","typeGuard":null,"tryCatchPattern":"try {\n  nameNode.setState(targetState);\n} catch (ServiceFailedException e) {\n  // re-read state, re-plan a legal path (via STANDBY), then retry once\n  HAServiceState cur = readServiceState();\n  LOG.warn(\"transition to \" + targetState + \" rejected from \" + cur, e);\n  transitionViaStandby(cur, targetState);\n}","preventionTips":["Model transitions as a graph (only the legal edges) in failover tooling instead of free-form commands","Script 'check state, then transition, then verify state' as one unit","Prefer automatic failover (ZKFC) over chained manual haadmin commands","Treat OBSERVER as reachable only from STANDBY in runbooks"],"tags":["hadoop","hdfs","high-availability","namenode","state-machine","failover"],"backgroundTag":"ha-state-transition-rejected","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}