Using form_set_error in the submit handler
In case it's useful to anyone else, I have a unsatisfactory work around;

Store the error in form_state, and look for them in the form callback.

function example_form($form, &amp;$form_state) {
  // if we had an error in the submit handler, trigger it now
  if(isset($form_state['error']) &amp;&amp; $form_state['error']){
    form_set_error('test', 'test');
  }
  if(!isset($form_state['step'])){
    $form_state['step'] = 1;
  }
  $form['test'] = array('#markup' =&gt; '&lt;p&gt;Step: ' . $form_state['step'] . '&lt;/p&gt;');

  $form['submit'] = array(
    '#type' =&gt; 'submit',
    '#value' =&gt; 'go'
  );
  return $form;
}


function example_submit($form, &amp;$form_state) {

  $form_state['rebuild'] = TRUE;
  if($form_state['step'] &gt; 5){
    //store error and return before the step is increased
    $form_state['error'] = true;
    return;
  }


  $form_state['step']++;
}