apache/hadoop · error · IOException
Uninitialized InputSplit
Error message
Uninitialized InputSplit
What it means
CompositeInputSplit holds N child splits for a join; the array is only allocated by the capacity constructor (or by readFields during deserialization). The no-arg constructor — meant for Writable deserialization — leaves splits null, and add() then throws this IOException ('Uninitialized InputSplit') before the capacity check ('Too many splits') can even run. Calling add() on a freshly reflect-constructed instance is the classic trigger.
Source
Thrown at hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapred/join/CompositeInputSplit.java:58
private int fill = 0;
private long totsize = 0L;
private InputSplit[] splits;
public CompositeInputSplit() { }
public CompositeInputSplit(int capacity) {
splits = new InputSplit[capacity];
}
/**
* Add an InputSplit to this collection.
* @throws IOException If capacity was not specified during construction
* or if capacity has been reached.
*/
public void add(InputSplit s) throws IOException {
if (null == splits) {
throw new IOException("Uninitialized InputSplit");
}
if (fill == splits.length) {
throw new IOException("Too many splits");
}
splits[fill++] = s;
totsize += s.getLength();
}
/**
* Get ith child InputSplit.
*/
public InputSplit get(int i) {
return splits[i];
}
/**
* Return the aggregate length of all child InputSplits currently added.
*/View on GitHub (pinned to 2add963021)
Solutions
- Always construct with the join arity: new CompositeInputSplit(2) for a two-way join.
- When building via a framework, ensure the join expression's arity and the split capacity agree.
- Instances obtained via readFields are already sized — never reuse a no-arg instance for manual population.
Example fix
// before CompositeInputSplit split = new CompositeInputSplit(); split.add(leftSplit); // throws // after CompositeInputSplit split = new CompositeInputSplit(2); split.add(leftSplit); split.add(rightSplit);
Defensive patterns
Strategy: validation
Validate before calling
// always size the composite split to the join arity before adding
int arity = 2; // number of join inputs
CompositeInputSplit split = new CompositeInputSplit(arity);
if (splitCount == arity) throw new IOException("Too many splits"); Type guard
static boolean isInitialized(CompositeInputSplit s) {
// no public accessor; treat any instance from new CompositeInputSplit() as uninitialized
return wasConstructedWithCapacity; // track construction site in your own wrapper
} Try / catch
try {
split.add(child);
} catch (IOException e) {
if (e.getMessage().equals("Uninitialized InputSplit")) {
throw new IllegalStateException("Construct with new CompositeInputSplit(arity)", e);
}
throw e;
} Prevention
- Always pass capacity: new CompositeInputSplit(n) matching the number of join inputs.
- Reserve the no-arg constructor for Writable deserialization only.
- When using join frameworks, keep the join expression arity and split capacity consistent.
When it happens
Trigger: new CompositeInputSplit() followed by add(split); a join framework (CompositeRecordReader) built with an arity/capacity mismatch so the split is never sized; reflection-based factories that use the default constructor.
Common situations: Hand-rolled map-side join plumbing; copy-pasted examples that drop the capacity argument; serializers that deserialize into a properly sized instance but user code that constructs one manually.
Related errors
- Error gathering splits from child RReader
- Inconsistent split cardinality from child {} ({}/{})
- Invalid split type:{}
- Input only available on map
- Too many splits
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/cfebd1fe72ae94c6.
Report an issue: GitHub.