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:


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->client = \Drupal::service('http_client');

  public function listProjects() {
    $select_form = \Drupal::formBuilder()->getForm('Drupal\myModule\Form\ExpeditionSelectForm');
    // Remove the submit button.

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

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

    return array(
      '#theme' => 'myModule_expeditions',
      '#form' => $select_form,

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

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

    $response->addCommand(new HtmlCommand(
        '#theme' => 'myModule_expeditions_detail',
        '#expedition' => $expedition,

    return $response;

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

    return array(
      '#theme' => 'myModule_deployment_detail',
      '#deployment' => json_decode($result->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' => 'select',
      '#title' => $this->t('Choose Project'),
      '#empty_option' => $this->t('Select a project'),
      '#default_value' => '',
      '#ajax' => [
        'callback' => '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 [];

1 Answer 1


You change the options after the form is built:

 $select_form['expeditions']['#options'][$value->{'expedition'}->{'expeditionId'}] = $this->t($value->{'expedition'}->{'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."

  • thanks, I moved the code to fetch and set the options to the buildForm method of my form and everything works.
    – rodney757
    Commented May 19, 2016 at 19:27
  • I have my code already in the buildForm but it still gives me the error, your expertise would be helpful @4k4
    – harshal
    Commented Aug 5, 2019 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.