{"record":{"id":"e65476a06aa7f198","repo":"apache/hadoop","slug":"replica-of-type-getstate-does-not-support-get-e65476","errorCode":null,"errorMessage":"Replica of type ${getState()} does not support getRecoveryID","messagePattern":"Replica of type (.+?) does not support getRecoveryID","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/FinalizedReplica.java","lineNumber":132,"sourceCode":"  @Override  // Object\n  public int hashCode() {\n    return super.hashCode();\n  }\n  \n  @Override\n  public String toString() {\n    return super.toString();\n  }\n\n  @Override\n  public ReplicaInfo getOriginalReplica() {\n    throw new UnsupportedOperationException(\"Replica of type \" + getState() +\n        \" does not support getOriginalReplica\");\n  }\n\n  @Override\n  public long getRecoveryID() {\n    throw new UnsupportedOperationException(\"Replica of type \" + getState() +\n        \" does not support getRecoveryID\");\n  }\n\n  @Override\n  public void setRecoveryID(long recoveryId) {\n    throw new UnsupportedOperationException(\"Replica of type \" + getState() +\n        \" does not support setRecoveryID\");\n  }\n\n  @Override\n  public ReplicaRecoveryInfo createInfo() {\n    throw new UnsupportedOperationException(\"Replica of type \" + getState() +\n        \" does not support createInfo\");\n  }\n\n  @Override\n  public long getMetadataLength() {\n    if (metaLength < 0) {","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/FinalizedReplica.java#L114-L150","documentation":"Recovery IDs are bookkeeping that exists only on replicas under recovery; a FINALIZED FinalizedReplica never entered a recovery session, so getRecoveryID() throws UnsupportedOperationException. Seeing it means recovery logic reached a finalized replica without a state check.","triggerScenarios":"Calling getRecoveryID() on a replica with state FINALIZED: recovery or truncate code paths that enumerate all replicas and read recovery IDs, or custom logic that assumes getRecoveryID() is universally implemented.","commonSituations":"Custom block-recovery implementations; tests that exercise every replica in the volume map; refactored recovery flows where a state filter was dropped.","solutions":["Check replica.getState()/type before reading the recovery ID; only RUR/RBW/RWR replicas carry one.","Route recovery through ReplicaUnderReconstruction references obtained from the replicasBeingWritten map rather than raw volume-map scans.","Add regression tests covering finalized replicas in the affected flow.","If framework code is at fault, verify against the corresponding Hadoop JIRA and upgrade."],"exampleFix":"// before\nlong id = replica.getRecoveryID();\n\n// after\nif (replica.getState() != ReplicaState.FINALIZED) {\n  long id = replica.getRecoveryID();\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static boolean hasRecoveryId(ReplicaInfo r) {\n  ReplicaState s = r.getState();\n  return s == ReplicaState.RBW || s == ReplicaState.RWR || s == ReplicaState.RUR;\n}","tryCatchPattern":"try {\n  long id = replica.getRecoveryID();\n} catch (UnsupportedOperationException e) {\n  // FINALIZED replica has no recovery ID: fix the caller's replica selection\n}","preventionTips":["Read recovery IDs only from recovery-state replicas","Drive recovery from the replicasBeingWritten/underReconstruction bookkeeping, not volume-map scans","Treat UnsupportedOperationException from ReplicaInfo APIs as a caller defect, never retry it"],"tags":["replica","finalized","recovery","unsupported-operation","hdfs","datanode"],"backgroundTag":"unsupported-operation","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}