{"record":{"id":"0ea7e3b9d922df0a","repo":"apache/hadoop","slug":"no-directory-is-specified","errorCode":null,"errorMessage":"No directory is specified.","messagePattern":"No directory is specified\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java","lineNumber":1158,"sourceCode":"    List<StorageLocation> unchangedLocations = Lists.newArrayList();\n  }\n\n  /**\n   * Parse the new DFS_DATANODE_DATA_DIR value in the configuration to detect\n   * changed volumes.\n   * @param newVolumes a comma separated string that specifies the data volumes.\n   * @return changed volumes.\n   * @throws IOException if none of the directories are specified in the\n   * configuration, or the storage type of a directory is changed.\n   */\n  @VisibleForTesting\n  ChangedVolumes parseChangedVolumes(String newVolumes) throws IOException {\n    Configuration conf = new Configuration();\n    conf.set(DFS_DATANODE_DATA_DIR_KEY, newVolumes);\n    List<StorageLocation> newStorageLocations = getStorageLocations(conf);\n\n    if (newStorageLocations.isEmpty()) {\n      throw new IOException(\"No directory is specified.\");\n    }\n\n    // Use the existing storage locations from the current conf\n    // to detect new storage additions or removals.\n    Map<String, StorageLocation> existingStorageLocations = new HashMap<>();\n    for (StorageLocation loc : getStorageLocations(getConf())) {\n      existingStorageLocations.put(loc.getNormalizedUri().toString(), loc);\n    }\n\n    ChangedVolumes results = new ChangedVolumes();\n    results.newLocations.addAll(newStorageLocations);\n\n    for (Iterator<Storage.StorageDirectory> it = storage.dirIterator();\n         it.hasNext(); ) {\n      Storage.StorageDirectory dir = it.next();\n      boolean found = false;\n      for (Iterator<StorageLocation> newLocationItr =\n           results.newLocations.iterator(); newLocationItr.hasNext();) {","sourceCodeStart":1140,"sourceCodeEnd":1176,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java#L1140-L1176","documentation":"parseChangedVolumes builds StorageLocations from the submitted dfs.datanode.data.dir value; if the parse yields zero locations it throws IOException(\"No directory is specified.\") and the live volume refresh (refreshVolumes, driven by reconfiguring dfs.datanode.data.dir) aborts before touching any volume. The value must be a comma-separated list with at least one valid [TYPE]scheme://path entry.","triggerScenarios":"Submitting dfs.datanode.data.dir=\"\", \",\", whitespace, or entries that all fail URI parsing via 'hdfs dfsadmin -reconfig datanode ... start' or the reconfig JMX API; an unexpanded ${DATANODE_DIRS} placeholder renders to a single invalid location string.","commonSituations":"Ansible/Chef templates rendering an empty string when a variable is undefined; a 'remove volumes' attempt that blanks the field instead of listing the surviving dirs; CM/Ambari UI fields accidentally cleared before apply.","solutions":["Resubmit with at least one valid entry — the value is the complete desired volume set, e.g. [DISK]file:///data/dn1","To remove volumes, list only the directories to KEEP; never an empty string","To retire the very last volume, decommission the DataNode instead of live-removing it"],"exampleFix":"// before\n$ hdfs dfsadmin -reconfig datanode dn1:9867 start ... dfs.datanode.data.dir=\n// => IOException: No directory is specified.\n// after\n$ hdfs dfsadmin -reconfig datanode dn1:9867 start ... dfs.datanode.data.dir=[DISK]file:///data/dn1","handlingStrategy":"validation","validationCode":"Configuration c = new Configuration(false);\nc.set(DFS_DATANODE_DATA_DIR_KEY, newVolumes);\nif (DataNode.getStorageLocations(c).isEmpty()) {\n  throw new IllegalArgumentException(\"new dfs.datanode.data.dir parses to zero locations\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  dn.refreshVolumes? // internal; externally: reconfigure dfs.datanode.data.dir\n} catch (ReconfigurationException e) {\n  if (String.valueOf(e.getCause()).contains(\"No directory is specified\")) { /* resubmit full desired volume list */ }\n}","preventionTips":["The reconfig value is the complete desired volume set — never submit an empty string","Fail template rendering when the data-dir variable is undefined instead of emitting empty","To drop the last volume, decommission the DataNode"],"tags":["hadoop","hdfs","datanode","volume-management","reconfiguration","configuration"],"backgroundTag":"empty-storage-config","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}