Solving the ‘An illegal choice has been detected. Please contact the site administrator.’ error
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!