{"record":{"id":"869beb6332dd4b8f","repo":"apache/hadoop","slug":"detachblock-block-not-found-this","errorCode":null,"errorMessage":"detachBlock:Block not found. ${this}","messagePattern":"detachBlock:Block not found\\. (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/LocalReplica.java","lineNumber":238,"sourceCode":"   * When doing a DataNode upgrade, we create a bunch of hardlinks to each block\n   * file.  This cleverly ensures that both the old and the new storage\n   * directories can contain the same block file, without using additional space\n   * for the data.\n   *\n   * However, when we want to append to the replica file, we need to \"break\" the\n   * hardlink to ensure that the old snapshot continues to contain the old data\n   * length.  If we failed to do that, we could roll back to the previous/\n   * directory during a downgrade, and find that the block contents were longer\n   * than they were at the time of upgrade.\n   *\n   * @return true only if data was copied.\n   * @throws IOException\n   */\n  public boolean breakHardLinksIfNeeded() throws IOException {\n    final File file = getBlockFile();\n    final FileIoProvider fileIoProvider = getFileIoProvider();\n    if (file == null || getVolume() == null) {\n      throw new IOException(\"detachBlock:Block not found. \" + this);\n    }\n    File meta = getMetaFile();\n\n    int linkCount = fileIoProvider.getHardLinkCount(getVolume(), file);\n    if (linkCount > 1) {\n      DataNode.LOG.info(\"Breaking hardlink for \" + linkCount + \"x-linked \" +\n          \"block \" + this);\n      breakHardlinks(file, this);\n    }\n    if (fileIoProvider.getHardLinkCount(getVolume(), meta) > 1) {\n      breakHardlinks(meta, this);\n    }\n    return true;\n  }\n\n  @Override\n  public URI getBlockURI() {\n    return getBlockFile().toURI();","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/LocalReplica.java#L220-L256","documentation":"breakHardLinksIfNeeded() (detach) requires a resolvable local block file and volume; if getBlockFile() or getVolume() returns null it throws IOException('detachBlock:Block not found. ' + this). The replica has no local file binding to break links on — typically a lost volume reference or a replica type that carries no local file.","triggerScenarios":"Calling breakHardLinksIfNeeded() on a replica whose volume was removed (failed disk, hot-unplug) or whose block file never resolved — e.g., provided replicas or replicas reconstructed after a restart without volume binding.","commonSituations":"Hard-link detach during an upgrade on a node where a volume just failed or was unmounted; DataNode restart mid-upgrade leaving replicas with null volume references; provided-storage replicas entering local-only detach flows.","solutions":["Check whether the replica's volume is still present in DataNode volume state (JMX FSDatasetStateInfo); fix the volume (remount/replace) before retrying the upgrade.","Restart the DataNode so volume and replica state is rebuilt consistently, then retry the operation.","Ensure the detach flow skips replicas without local files (e.g., PROVIDED).","If the block is effectively gone, let HDFS re-replicate it (verify with `hdfs fsck /`) before continuing the upgrade."],"exampleFix":"// before: detach every replica unconditionally\nfor (ReplicaInfo r : replicas) {\n  r.breakHardLinksIfNeeded();\n}\n\n// after: skip replicas with no local file binding\nfor (ReplicaInfo r : replicas) {\n  if (r.getBlockFile() != null && r.getVolume() != null) {\n    r.breakHardLinksIfNeeded();\n  }\n}","handlingStrategy":"validation","validationCode":"if (replica.getBlockFile() != null && replica.getVolume() != null) {\n  replica.breakHardLinksIfNeeded();\n} else {\n  // no local binding: skip (provided replica) or resolve the missing volume first\n}","typeGuard":null,"tryCatchPattern":"try {\n  replica.breakHardLinksIfNeeded();\n} catch (IOException e) {\n  if (e.getMessage().contains(\"detachBlock:Block not found\")) {\n    // volume lost or file unresolved: fix volume state / restart DN before retrying\n  }\n}","preventionTips":["Resolve volume failures before starting upgrades that break hard links","Skip replicas without local files (PROVIDED) in detach flows","Restart the DataNode after volume changes so replica-to-volume bindings are rebuilt"],"tags":["block","hardlink","volume","hdfs","datanode"],"backgroundTag":"missing-block-file","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}