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

  1. Always construct with the join arity: new CompositeInputSplit(2) for a two-way join.
  2. When building via a framework, ensure the join expression's arity and the split capacity agree.
  3. 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

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


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/cfebd1fe72ae94c6. Report an issue: GitHub.