An illegal choice has been detected. after leaving form page I have a form with only a select element and no submit button. Upon change, I issue an ajax call to retrieve the details of the selected Project. Everything works as expected, however after I leave the page, I see the error "An illegal choice has been detected. Please contact the site administrator."

I only get the error if I change the select input. Ex. if I navigate to:


  Home->Projects->Home


I don't see the error on the last Home page. If i navigate to:


  Home->Projects(change select input)->Home


I see the error on the last Home page.

Here is my module code:

class ExpeditionController extends ControllerBase {
  public $client;

  public function __construct() {
    $this-&gt;client = \Drupal::service('http_client');
  }


  public function listProjects() {
    $select_form = \Drupal::formBuilder()-&gt;getForm('Drupal\myModule\Form\ExpeditionSelectForm');
    // Remove the submit button.
    unset($select_form['actions']['submit']);

    $result = $this-&gt;client-&gt;get('myRESTService', ['Accept' =&gt; 'application/json']);
    $expeditions = json_decode($result-&gt;getBody());

    foreach ($expeditions as $value) {
      $select_form['expeditions']['#options'][$value-&gt;{'expedition'}-&gt;{'expeditionId'}] = $this-&gt;t($value-&gt;{'expedition'}-&gt;{'expeditionTitle'});
    }

    return array(
      '#theme' =&gt; 'myModule_expeditions',
      '#form' =&gt; $select_form,
    );
  }

  public function expeditionDetail($form, $form_state) {
    $expedition = [];
    $response = new AjaxResponse();
    if ($form['expeditions']['#value'] != "") {

      $client = \Drupal::service('http_client');
      $result = $client-&gt;get(
        'myService' . $form['expeditions']['#value'],
        ['Accept' =&gt; 'application/json']
      );
      $expedition = json_decode($result-&gt;getBody());
    }

    $response-&gt;addCommand(new HtmlCommand(
      '#expeditionDetail',
      array(
        '#theme' =&gt; 'myModule_expeditions_detail',
        '#expedition' =&gt; $expedition,
      )
    ));

    return $response;
  }

  public function deploymentDetail($project_id, $deployment_id) {
    $result = $this-&gt;client-&gt;get(
      'myService' . $project_id . '/' . $deployment_id,
      ['Accept' =&gt; 'application/json']
    );

    return array(
      '#theme' =&gt; 'myModule_deployment_detail',
      '#deployment' =&gt; json_decode($result-&gt;getBody()),
    );

  }
}

class ExpeditionSelectForm extends ConfigFormBase {
  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'myModule_expeditions';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['expeditions'] = array(
      '#type' =&gt; 'select',
      '#title' =&gt; $this-&gt;t('Choose Project'),
      '#empty_option' =&gt; $this-&gt;t('Select a project'),
      '#default_value' =&gt; '',
      '#ajax' =&gt; [
        'callback' =&gt; 'Drupal\myModule\Controller\ExpeditionController::expeditionDetail',
      ],
    );

    return parent::buildForm($form, $form_state);
  }

  /**
   * Gets the configuration names that will be editable.
   *
   * @return array
   *   An array of configuration object names that are editable if called in
   *   conjunction with the trait's config() method.
   */
  protected function getEditableConfigNames() {
    // TODO: Implement getEditableConfigNames() method.
    return [];
  }
}
You change the options after the form is built:

 $select_form['expeditions']['#options'][$value-&gt;{'expedition'}-&gt;{'expeditionId'}] = $this-&gt;t($value-&gt;{'expedition'}-&gt;{'expeditionTitle'});


The Form API doesn't know about this. On submit the Form API checks if the submitted option is in the original option list. If not, it rejects the submit with the error "An illegal choice has been detected. Please contact the site administrator."