Solving the ‘An illegal choice has been detected. Please contact the site administrator.’ error
Posted by Kim | Posted in Drupal, PHP | Posted on 13-08-2009
12
After upgrading a couple of client websites to Drupal 6.13, we suddenly noticed several “An illegal choice has been detected. Please contact the site administrator.” errors. These errors popped up all around: Performance settings, User adding, u name it.
Research thought me that the illegal choice error was returned when the posted! value of a checkbox, select or radio form field was not available in the original form-structure array. It all sounds logical as an valid input filter, because you don’t want people posting illegal values in your forms now do you?
I found out that the code generating the radio buttons was the following:
We were able to trace it back to the following piece of code in /includes/form.inc line 1733
1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 | /** * Roll out a single radios element to a list of radios, * using the options array as index. */ function expand_radios($element) { if (count($element['#options']) > 0) { foreach ($element['#options'] as $key => $choice) { if (!isset($element[$key])) { // Generate the parents as the autogenerator does, so we will have a // unique id for each radio button. $parents_for_id = array_merge($element['#parents'], array($key)); $element[$key] = array( '#type' => 'radio', '#title' => $choice, '#return_value' => check_plain($key), '#default_value' => isset($element['#default_value']) ? $element['#default_value'] : NULL, '#attributes' => $element['#attributes'], '#parents' => $element['#parents'], '#id' => form_clean_id('edit-'. implode('-', $parents_for_id)), '#ahah' => isset($element['#ahah']) ? $element['#ahah'] : NULL, ); } } } return $element; } |
and more specifically this line (1747):
1747 | '#return_value' => check_plain($key), |
Tracking down further learns us the source of all evil hides in bootstrap.inc line 728!
728 729 730 731 732 733 734 735 736 | /** * Encode special characters in a plain-text string for display as HTML. * * Uses drupal_validate_utf8 to prevent cross site scripting attacks on * Internet Explorer 6. */ function check_plain($text) { return drupal_validate_utf8($text) ? htmlspecialchars($text, ENT_QUOTES) : ''; } |
This little piece checks if the passed argument is a valid UTF8 string, and if so htmlspecialchars it, or if not, returns nothing! This causes the return values of our radio button items to have an empty value=”" attribute, causing the validation to fail because of the empty value you posted.
Change it to this code to get it back up on it’s feet:
728 729 730 731 732 733 734 735 736 | /** * Encode special characters in a plain-text string for display as HTML. * * Uses drupal_validate_utf8 to prevent cross site scripting attacks on * Internet Explorer 6. */ function check_plain($text) { return drupal_validate_utf8($text) ? htmlspecialchars($text, ENT_QUOTES) : $text; } |
Hope to be of any service!



This change is in fact removal of security measures (instead of rejecting broken utf8 for security reasons, we now return it, even skipping safety-escaping!) We might better think about WHY check_plain was used on checkboxes.
Hi JirkaRybka,
I completely agree with you on the security matter, but the problem is situated in the fact that when running numerical values like 0 or 1 through check_plain, the returned value was empty.
This returns in empty radio-buttons and thus “illegal choices”.
Greets
Dear author,
I am afraid I was not able to solve my problems with your suggestions. While browsing through the form.inc file, I noticed that the problem lies _form_validate function (Which is used if anyone intends to use the built in form validation techniques implemented in the Forms API.)
In that, it specifically states its function as:
* Performs validation on form elements. First ensures required fields are
* completed, #maxlength is not exceeded, and selected options were in the
* list of options given to the user. Then calls user-defined validators.
*
Hello Author,
I am facing same problem when i am populating data into selectbox through ajax when user select any value from it’s parent select box.I tried the above trick but it seems not working for me.
I search lot nothing appears to be working for me.
Please help
Hi Nehal,
This issue originates from the fact that a value was posted, which was not in the original form-setup array, and thus forms an illegal choice
when matching the posted values against the proposed values in the form-array.
Populating your (connected) select boxes through ajax is a good technique, although you should have a look at the following implementations:
I hope I have put you on the right track, otherwise come back for more!
Kind regards,
Kim
When doing Ajax select, we get this error when the form field which is being replaced by ajax is a required field. Making it optional will do the trick.
I have the same issue as Nehal. I looked at the code for Hierarchical Select, I didn’t find any answers there. How can I update the original form array via JavaScript? Can I update the array via the PHP hook_user validate $op? I need to use the hook_user validate as have a custom panel in the register form.
Hi Stuart, check the AHAH example module (http://drupal.org/project/examples) to find out how you can create a correct Hierarchical select structure.
Also the AHAH helper module (http://drupal.org/project/ahah_helper) is a great asset!
Greets.
Any chance that somebody could point us to a specific function or line of code in one of these modules to get around this problem so we don’t have to start from line 1?
You can comment out the right lines in _validate_form function (where form_error() runs) but thats not very elegant…
Try adding ‘#validated’ => ‘TRUE’ to form elements definitions:
form['my_dynamic_select'] = array(
‘#type’ => ‘select’,
‘#validated’ => TRUE
…
)
“Hi JirkaRybka,
I completely agree with you on the security matter, but the problem is situated in the fact that when running numerical values like 0 or 1 through check_plain, the returned value was empty.
This returns in empty radio-buttons and thus “illegal choices”.”
Hi, author, I totally agree with what you explained here. I have got the same problem. I write a radios button in custom module. and cannot get default value for radios…..so it shows me this error. would you explain a little bit how to set default value for radios. I did try to search online. thanks
Thanks “Mike” said on 17-06-2011 , Its really great.. it works.. !!