I was able to reproduce with a similar script that didn't have a reducer in the first MR job. The code in questions is this block in SampleOptimizer. It returns in the second conditional with Predecessor should be a root of the plan before reducers can be estimated.
// Get this job's predecessor. There should be exactly one.;
List<MapReduceOper> preds = mPlan.getPredecessors(mr);
if (preds.size() != 1)
log.debug("Too many predecessors to sampling job.");
MapReduceOper pred = preds.get(0);
// The predecessor should be a root.
List<MapReduceOper> predPreds = mPlan.getPredecessors(pred);
if (predPreds != null && predPreds.size() > 0)
log.debug("Predecessor should be a root of the plan");
// The predecessor should have just a load and store in the map, and nothing
// in the combine or reduce.
if ( !(pred.reducePlan.isEmpty() && pred.combinePlan.isEmpty()))
log.debug("Predecessor has a combine or reduce plan");