apache/hadoop · error · HadoopIllegalArgumentException
Missing storageIDs: It is likely that the HDFS client, who m
Error message
Missing storageIDs: It is likely that the HDFS client, who made this call, is running in an older version of Hadoop(pre-2.0.0-alpha) which does not support storageIDs. datanodeID.length={datanodeID.length} What it means
Thrown as HadoopIllegalArgumentException from DatanodeManager.getDatanodeStorageInfos when the datanodeID array and storageIDs array lengths differ; the specific 'Missing storageIDs' text appears when storageIDs is empty, which indicates a pre-2.0.0-alpha client that does not understand per-storage identifiers. Callers pass paired (datanode, storageID) lists — e.g., pipeline recovery and block token renewal — and an empty/short storageIDs list cannot identify which storage to act on.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeManager.java:841
+ e.getLocalizedMessage());
throw e;
}
return node;
}
public DatanodeStorageInfo[] getDatanodeStorageInfos(
DatanodeID[] datanodeID, String[] storageIDs,
String format, Object... args) throws UnregisteredNodeException {
storageIDs = storageIDs == null ? new String[0] : storageIDs;
if (datanodeID.length != storageIDs.length) {
// Error for pre-2.0.0-alpha clients.
final String err = (storageIDs.length == 0?
"Missing storageIDs: It is likely that the HDFS client,"
+ " who made this call, is running in an older version of Hadoop"
+ "(pre-2.0.0-alpha) which does not support storageIDs."
: "Length mismatched: storageIDs.length=" + storageIDs.length + " != "
) + " datanodeID.length=" + datanodeID.length;
throw new HadoopIllegalArgumentException(
err + ", "+ String.format(format, args));
}
if (datanodeID.length == 0) {
return null;
}
final DatanodeStorageInfo[] storages = new DatanodeStorageInfo[datanodeID.length];
for(int i = 0; i < datanodeID.length; i++) {
if (datanodeID[i].equals(DatanodeID.EMPTY_DATANODE_ID)) {
storages[i] = null;
continue;
}
final DatanodeDescriptor dd = getDatanode(datanodeID[i]);
if (dd != null) {
storages[i] = dd.getStorageInfo(storageIDs[i]);
}
}
return storages;
}View on GitHub (pinned to 2add963021)
Solutions
- Upgrade the client to a Hadoop 2.0.0-alpha+ (ideally cluster-matching) version so storageIDs are populated
- In custom code, always pass a storageIDs array of equal length, obtained from LocatedBlock.getLocatedBlocks() storageIDs
- If mid-upgrade, complete the rolling upgrade so all components speak the storage-aware protocol
- Verify with the exception's suffix (format/args) which call path produced it and check that client's version
Example fix
// before: building targets without storage IDs DatanodeID[] dns = ...; String[] sids = null; // -> Missing storageIDs // after: derive storageIDs from the located block LocatedBlock lb = namenode.addBlock(src, clientName, previous, null, ...); DatanodeID[] dns = toDatanodeID(lb.getLocations()); String[] sids = lb.getStorageIDs(); // same length as dns namenode.updatePipeline(clientName, oldBlock, newBlock, dns, sids);
Defensive patterns
Strategy: validation
Validate before calling
// Always pass equal-length arrays derived from a LocatedBlock
DatanodeID[] dns = Arrays.stream(lb.getLocations()).map(DatanodeInfo::new).toArray(DatanodeID[]::new);
String[] storageIDs = lb.getStorageIDs();
assert dns.length == storageIDs.length && storageIDs.length > 0
: "storageIDs missing — client/library too old or bad LocatedBlock";
nn.updatePipeline(clientName, oldBlock, newBlock, dns, storageIDs); Try / catch
try {
nn.updatePipeline(clientName, old, neu, dns, storageIDs);
} catch (HadoopIllegalArgumentException e) {
if (e.getMessage().contains("storageIDs")) {
// rebuild from a fresh LocatedBlock via addBlock; never mix old client arrays
LocatedBlock lb = nn.addBlock(src, clientName, neu, null, null, null);
nn.updatePipeline(clientName, old, lb.getBlock(), toIDs(lb), lb.getStorageIDs());
} else { throw e; }
} Prevention
- Use a Hadoop 2.x+ client; retire 0.20/1.x-era libraries
- Always source (datanodeID, storageID) pairs from LocatedBlock, never construct one side manually
- During rolling upgrades, finish the upgrade before exercising pipeline-recovery RPCs
- Add unit asserts on array-length equality in client wrappers
When it happens
Trigger: An ancient client RPC (or code constructing these arrays without storageIDs) calls an API (e.g., updateBlockForPipeline/updatePipeline or DN-side getDatanodeStorageInfos usage) where datanodeID.length != storageIDs.length with storageIDs empty; length-mismatch variant also fires on partially built arrays.
Common situations: Mixing a pre-2.0 (0.20/1.x-era) client library with a modern cluster; custom tooling building DatanodeID[] but passing null/empty storageIDs; version-skew during rolling upgrades.
Related errors
- Processing RPC request caught
- Unsupported protocol found when creating the proxy connectio
- Replica was found but missing fields.
- Did not get any valid JournaledEdits responses: " + msg
- Datanode {datanode} not found.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/6e56dc035f10cc65.
Report an issue: GitHub.