When receiving a logic error such as
LogicException: Form errors cannot be set after form validation has finished. in Drupal\Core\Form\FormState->setErrorByName() (line 1104 of /var/www/html/project/core/lib/Drupal/Core/Form/FormState.php).
This error "LogicException: Form errors cannot be set after form validation has finished," indicates that the setErrorByName() function is being called at an inappropriate time in the form processing lifecycle. Specifically, this error occurs when an attempt is made to set an error on the form after the validation phase has completed, which is against Drupal's form handling workflow.
The Drupal form lifecycle is:
Build Phase
The form is constructed and elements are defined.
Validation Phase
Input values are checked for errors
This is where you should set any validation-related errors using setErrorByName().
Submission Phase
If the validation passes, this phase processes the data.
The error setting is attempted during the AJAX callback or a submission handler, which are executed after the form's validation phase has completed.
Solution
Move Validation to a Proper Validator: Ensure that the validation logic (isValidInput($question)) is part of a validation function linked to the form. This could be in a custom validation handler that you add to the form array during the form build phase.Here’s how you can add a custom validation handler:
public function buildForm(array $form, FormStateInterface $form_state) {
// Existing setup code...
// Add a custom validation handler
$form['#validate'][] = '::validateForm';
// Rest of your form setup...
return $form;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
$question_raw = $form_state->getValue('question');
$question = Xss::filter($question_raw);
// Run validation checks.
if (!$this->isValidInput($question)) {
$form_state->setErrorByName('question', $this->t('Invalid input. Please enter a valid value.'));
}
}
Adjust AJAX Callback
If you need to perform additional checks or actions in an AJAX callback, ensure that any state modification or error handling that depends on validation occurs within the validation phase or is handled in a way that does not conflict with the form's workflow. If you need to return feedback or updates via AJAX, consider using form state's storage to pass information or adjust your AJAX response handling to reflect the form's state without violating the lifecycle.
Check Form State Management
Ensure that you are not inadvertently causing the form to process validation or submission logic multiple times or in the wrong order. This can sometimes happen with complex AJAX interactions or if form rebuilding is not managed correctly.
Through aligning your error handling and validation logic with Drupal's form processing phases, you should be able to resolve the LogicException and ensure that your form behaves as expected, providing timely and user-friendly feedback for form submissions and AJAX interactions.