apache/hadoop · error · IOException
Changing storage type is not allowed.
Error message
Changing storage type is not allowed.
What it means
During refreshVolumes, every new location that matches an existing StorageDirectory is compared against the previously configured location for the same normalized URI; if the storage type differs (oldLocation.getStorageType() != newLocation.getStorageType()), HDFS throws IOException("Changing storage type is not allowed.") because a live volume cannot be retyped in place. No volumes are modified when this fires.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java:1183
existingStorageLocations.put(loc.getNormalizedUri().toString(), loc);
}
ChangedVolumes results = new ChangedVolumes();
results.newLocations.addAll(newStorageLocations);
for (Iterator<Storage.StorageDirectory> it = storage.dirIterator();
it.hasNext(); ) {
Storage.StorageDirectory dir = it.next();
boolean found = false;
for (Iterator<StorageLocation> newLocationItr =
results.newLocations.iterator(); newLocationItr.hasNext();) {
StorageLocation newLocation = newLocationItr.next();
if (newLocation.matchesStorageDirectory(dir)) {
StorageLocation oldLocation = existingStorageLocations.get(
newLocation.getNormalizedUri().toString());
if (oldLocation != null &&
oldLocation.getStorageType() != newLocation.getStorageType()) {
throw new IOException("Changing storage type is not allowed.");
}
// Update the unchanged locations as this location
// from the new conf is really not a new one.
newLocationItr.remove();
results.unchangedLocations.add(newLocation);
found = true;
break;
}
}
// New conf doesn't have the storage location which available in
// the current storage locations. Add to the deactivateLocations list.
if (!found) {
LOG.info("Deactivation request received for active volume: {}",
dir.getRoot());
results.deactivateLocations.add(
StorageLocation.parse(dir.getRoot().toString()));
}View on GitHub (pinned to 2add963021)
Solutions
- Split into two reconfigs: first submit the value WITHOUT the location (it deactivates), then re-add it with the new type prefix in a second reconfig
- Or stop the DataNode, update dfs.datanode.data.dir, and restart — the startup path re-reads types cleanly
- Double-check every bracketed prefix; a missing prefix means DISK
Example fix
# before (single reconfig, rejected) dfs.datanode.data.dir=[SSD]file:///data/dn1,[DISK]file:///data/dn2 # after step 1: drop dn1 dfs.datanode.data.dir=[DISK]file:///data/dn2 # after step 2: re-add with the new type dfs.datanode.data.dir=[SSD]file:///data/dn1,[DISK]file:///data/dn2
Defensive patterns
Strategy: validation
Validate before calling
Map<String, StorageType> oldByUri = new HashMap<>();
for (StorageLocation l : DataNode.getStorageLocations(currentConf))
oldByUri.put(l.getNormalizedUri().toString(), l.getStorageType());
for (StorageLocation l : newLocations) {
StorageType t = oldByUri.get(l.getNormalizedUri().toString());
if (t != null && t != l.getStorageType())
throw new IllegalArgumentException("cannot retype " + l + " from " + t);
} Try / catch
catch (ReconfigurationException e) {
if (String.valueOf(e.getCause()).contains("Changing storage type")) {
// split into remove-then-re-add with the new type, in two separate reconfigs
}
} Prevention
- Type prefixes are part of a volume's identity — never edit them in place in the reconfig value
- Plan type migrations as remove-then-readd, with data re-replication in between if needed
- Diff old vs new dfs.datanode.data.dir per normalized URI before every volume refresh
When it happens
Trigger: Live-reconfiguring dfs.datanode.data.dir where an existing path's bracketed type prefix changes: [DISK]file:///data/dn1 -> [SSD]file:///data/dn1, or dropping the prefix entirely (default DISK) where the old config had [ARCHIVE]/[SSD], or vice versa.
Common situations: Tiering a hot volume to SSD/NVMe; unifying per-host configs where one host had explicit type prefixes and the shared template omits them; typos in type names that silently become DISK and collide with an old typed entry.
Related errors
- No directory is specified.
- Attempt to remove all volumes.
- Not a valid Boolean value for {property} in reconfSlowPeerPa
- FsDatasetSpi has not been initialized
- Not a valid Boolean value for {property}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/66879404c5eead1e.
Report an issue: GitHub.