Using form_set_error in the submit handler I have a multistep form and on each submit I send completed fields off to an external API which returns data about the next step of the form.

The problem is, if I use form_set_error in the submit handler, the form_storage is cleared and so the form resets to the first page.

Here's a arbitrary example;

function example_form($form, &amp;$form_state) {
  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_form_submit($form, &amp;$form_state) {
  $form_state['rebuild'] = TRUE;
  if($form_state['step'] &gt; 5){
    form_set_error('test', 'error');
    return;
  }
  $form_state['step']++;
}


So this create a form with just a text block displaying the step number and a submit button that takes you to the next step. Until you go past the 5th step at which point it should start to error.

For some reason in my testing this breaks the step count, and on error takes you back to step 2.

moving the form_set_error into the form callback, or into a validate callback fixes the issue, but it would be cleaner if I could call it 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']++;
}