Why is submit handler not called if $state['rebuild'] == true? I have a simple form that shows a form fields and after submitting shows just a download link:

function activit_report_download_file_form($form, &amp;$state, $node) {

// check if form was already submitted
$submitted = false;
if(isset($state['triggering_element'])) {
  $submitted = true;

  if(!valid_email_address($state['values']['email'])) { $submitted = false; }
  if(strlen($state['values']['name'])&lt;2) { $submitted = false; }
  if(strlen($state['values']['surname'])&lt;2) { $submitted = false; }
}

if(!user_is_logged_in() &amp;&amp; !$submitted) {

  $form['info'] = array(
      '#type' =&gt; 'markup',
      '#markup' =&gt; '&lt;div class="info"&gt;'.t('Po vyplnení Vaších údajov si budete môcť stiahnuť PDF report').'&lt;/div&gt;&lt;br&gt;'
  );

  $form['email'] = array(
      '#type' =&gt; 'textfield',
      '#attributes' =&gt; array('placeholder' =&gt; t('Váš email'))
  );

  $form['name'] = array(
      '#type' =&gt; 'textfield',
      '#attributes' =&gt; array('placeholder' =&gt; t('Váše meno'))
  );

  $form['surname'] = array(
      '#type' =&gt; 'textfield',
      '#attributes' =&gt; array('placeholder' =&gt; t('Váše priezvisko'))
  );

  $form['submit'] = array(
      '#type' =&gt; 'submit',
      '#value' =&gt; t('Získať link na stiahnutie reportu'),
      '#attributes' =&gt; array('class' =&gt; array('button', 'btn-blue')),

  );

} else {

  $form['link'] = array(
      '#type' =&gt; 'markup',
      '#markup' =&gt; '
        &lt;div class="info"&gt;Report stiahnete kliknutím na toto tlačítko.&lt;/div&gt;&lt;br&gt;
        &lt;a href="" class="button btn-orange"&gt;'.t('Stiahnuť PDF report').'&lt;/a&gt;'
  );

}

return $form;
}


In validation handler is $state['rebuild'] = true;

function activit_report_download_file_form_validate($form, &amp;$state) {

  $state['rebuild'] = true;

}


In submit handler is:

function activit_report_download_file_form_submit($form, &amp;$state) {

  db_insert('t_report_download')-&gt;fields(array(
      'email' =&gt; $state['values']['email'],
      'name' =&gt; $state['values']['name'],
      'surname' =&gt; $state['values']['surname'],
      'anonymous' =&gt; 1,
  ))-&gt;execute();

  dsm('submitted');
}


Problem is that submit handler is triggered only if $state['rebuild'] = true; in validation handler is commented. If it is not, submit handler will never be triggered. 

What's the logic behind this behavior?
When form validation fails submit handler should not be executed because there are errors in the form. 

In a similar way, when a form is mark as rebuild in the validation phase submit handlers should not be executed because the form is going to be rebuilt. This means that form is going to change and the user interaction with the form is not finished.

You can check the (complex) workflow of FAPI in this illustration:

(Illustration from https://www.drupal.org/node/165104)