{"record":{"id":"06217ae109ddd25e","repo":"apache/hadoop","slug":"replica-of-type-does-not-support-getrecoveryid","errorCode":null,"errorMessage":"Replica of type {} 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/ReplicaWaitingToBeRecovered.java","lineNumber":107,"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 getRecoveryID\");\n  }\n\n  @Override\n  public ReplicaRecoveryInfo createInfo() {\n    throw new UnsupportedOperationException(\"Replica of type \" + getState() +\n        \" does not support createInfo\");\n  }\n}\n","sourceCodeStart":89,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/ReplicaWaitingToBeRecovered.java#L89-L123","documentation":"ReplicaWaitingToBeRecovered.getRecoveryID() throws UnsupportedOperationException: an RWR replica carries no recovery id. Recovery ids exist only while a replica is actively under recovery (ReplicaUnderRecovery), which is a different state from merely waiting to be recovered after its writer died.","triggerScenarios":"Invoking getRecoveryID() on a ReplicaWaitingToBeRecovered instance - typically from generic recovery/monitoring code (metrics collectors, block scanners, tests) that walks the volume map and unconditionally reads recovery metadata.","commonSituations":"Block recovery tooling or tests that treat every replica in the volume map uniformly; code written against ReplicaUnderRecovery being handed an RWR replica after a recovery handshake aborts.","solutions":["Only call getRecoveryID() when replica.getState() == ReplicaState.RUR (or instanceof ReplicaUnderRecovery)","Return a sentinel (e.g., 0) in generic code paths for non-RUR replicas","Fix the caller: waiting-to-be-recovered replicas must first be wrapped in ReplicaUnderRecovery to gain a recovery id"],"exampleFix":"// before\nlong id = replica.getRecoveryID(); // throws for RWR\n\n// after\nlong id = (replica instanceof ReplicaUnderRecovery)\n    ? ((ReplicaUnderRecovery) replica).getRecoveryID()\n    : 0L;","handlingStrategy":"type-guard","validationCode":"long recoveryIdOrZero(ReplicaInfo r) { return (r instanceof ReplicaUnderRecovery) ? r.getRecoveryID() : 0L; }","typeGuard":"static boolean exposesRecoveryId(ReplicaInfo r) {\n  return r instanceof ReplicaUnderRecovery;\n}","tryCatchPattern":"try { id = r.getRecoveryID(); } catch (UnsupportedOperationException e) { id = 0L; /* caller treats 0 as 'not under recovery' */ }","preventionTips":["Volume-map walkers (scanners, metrics, tests) must special-case replica types before reading recovery metadata","Prefer state checks (RUR) over blanket method calls across heterogeneous replicas"],"tags":["hdfs","datanode","block-recovery","replica","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}