{"record":{"id":"51e919ae4ee49d51","repo":"apache/hadoop","slug":"not-enough-capacity-ratio-left-on-mount-mount","errorCode":null,"errorMessage":"Not enough capacity ratio left on mount: ${mount}, for ${target}: capacity ratio: ${capacityRatio}. Sum of the capacity ratio of on same disk mount should be <= 1","messagePattern":"Not enough capacity ratio left on mount: (.+?), for (.+?): capacity ratio: (.+?)\\. Sum of the capacity ratio of on same disk mount should be <= 1","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/MountVolumeMap.java","lineNumber":101,"sourceCode":"  void removeVolume(FsVolumeImpl target) {\n    String mount = target.getMount();\n    if (!mount.isEmpty()) {\n      MountVolumeInfo info = mountVolumeMapping.get(mount);\n      info.removeVolume(target);\n      if (info.size() == 0) {\n        mountVolumeMapping.remove(mount);\n      }\n    }\n  }\n\n  void setCapacityRatio(FsVolumeImpl target, double capacityRatio)\n      throws IOException {\n    String mount = target.getMount();\n    if (!mount.isEmpty()) {\n      MountVolumeInfo info = mountVolumeMapping.get(mount);\n      if (!info.setCapacityRatio(\n          target.getStorageType(), capacityRatio)) {\n        throw new IOException(\n            \"Not enough capacity ratio left on mount: \"\n                + mount + \", for \" + target + \": capacity ratio: \"\n                + capacityRatio + \". Sum of the capacity\"\n                + \" ratio of on same disk mount should be <= 1\");\n      }\n    }\n  }\n\n  public boolean hasMount(String mount) {\n    return mountVolumeMapping.containsKey(mount);\n  }\n}\n","sourceCodeStart":83,"sourceCodeEnd":114,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/MountVolumeMap.java#L83-L114","documentation":"Thrown by MountVolumeMap.setCapacityRatio() (MountVolumeMap.java:101) during DataNode startup or volume refresh when same-disk tiering (HDFS-15548) is enabled and the configured capacity ratios of volumes sharing one disk mount sum to more than 1. Ratios come from dfs.datanode.same-disk-tiering.capacity-ratio.percentage entries of the form [ratio]/path (e.g. [0.3]/disk1/archive), and MountVolumeInfo.setCapacityRatio refuses an assignment that overcommits the mount.","triggerScenarios":"dfs.datanode.same-disk-tiering.enabled=true plus capacity-ratio entries whose ratios on the same mount exceed 1.0 (e.g. [0.6]/mnt/disk/archive and [0.5]/mnt/disk/disk); ratios fine individually but paths resolve to the same mount via symlinks/bind mounts; typo like [1.2]/path passing StorageLocation's 0-1 check is impossible, but two 0.9 entries on one mount is the classic hit.","commonSituations":"Enabling block tiering (ARCHIVE + DISK volumes on one physical disk) and copy-pasting ratio entries; re-arranging directories so two configured volumes now share a mount; changing one volume's ratio and forgetting the counterpart's; volume refresh (dfsadmin -refreshNodes-style reconfiguration) after editing the ratio property.","solutions":["Sum the ratios for every configured volume on the same mount and reduce them so the total is <= 1 (e.g. [0.3]/disk1/archive + [0.7]/disk1/disk)","Verify each path really lands on the mount you think (df/realpath on the volume dirs) - symlinked paths silently share mounts","Keep each individual ratio within 0..1 as StorageLocation.parseCapacityRatio requires","If tiering is not intended, remove the capacity-ratio entries or set dfs.datanode.same-disk-tiering.enabled=false and restart the DataNode","Apply the corrected value, then re-run refresh or restart; the check re-executes at volume initialization"],"exampleFix":"# before: two volumes on /mnt/disk0 overcommit the mount (0.6 + 0.5 > 1)\n<property>\n  <name>dfs.datanode.same-disk-tiering.capacity-ratio.percentage</name>\n  <value>[0.6]/mnt/disk0/archive,[0.5]/mnt/disk0/disk</value>\n</property>\n\n# after: ratios on one mount sum to exactly 1\n<property>\n  <name>dfs.datanode.same-disk-tiering.capacity-ratio.percentage</name>\n  <value>[0.3]/mnt/disk0/archive,[0.7]/mnt/disk0/disk</value>\n</property>","handlingStrategy":"validation","validationCode":"// before enabling same-disk tiering: parse the config and sum per mount\nMap<String, Double> perMount = new HashMap<>();\nfor (Map.Entry<URI, Double> e : StorageLocation.parseCapacityRatio(conf.get(\n        \"dfs.datanode.same-disk-tiering.capacity-ratio.percentage\", \"\")).entrySet()) {\n  String mount = org.apache.hadoop.fs.FileSystem.getStoreMount(e.getKey()); // or df-based lookup\n  double sum = perMount.getOrDefault(mount, 0.0) + e.getValue();\n  if (sum > 1.0) {\n    throw new IllegalArgumentException(\"Ratios on mount \" + mount + \" sum to \" + sum);\n  }\n  perMount.put(mount, sum);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the per-mount ratio budget documented next to the config so edits preserve sum <= 1","Resolve volume paths with df/realpath before assigning ratios - symlinks make two dirs share a mount","Remember one volume per storage type per mount; ratios are per storage type","Validate the property format ([ratio]/path, comma-separated) in CI/config management before deploy"],"tags":["hdfs","datanode","same-disk-tiering","configuration","capacity-ratio"],"backgroundTag":"config-value-out-of-range","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}