In my module routing I have a custom access callback for a payment page.

_custom_access: 'Drupal\mymodule\Form\PaymentForm::access'

It checks if the user:

  • is allowed to make the payment (it's their own)
  • actually needs to (has it already been paid)

It works fine, but in the latter case, whilst I can give them an explanatory warning:

\Drupal::messenger()->addWarning('Fee already paid or no fee to pay.');
return AccessResult::forbidden();

it'd be nicer to redirect them to a page that's friendlier than:

Access Denied - you are not authorised to access the page.

Drupal / Symfony insists on returning something that implements AccessResult - so I can't return a RedirectResponse. Any suggestions? Moving the checks to buildForm() seems a bad idea.

1 Answer 1


For the second condition an access denied doesn't seem to be the right answer because permissions are not the reason. It is to control the business logic and for this I think it is a good idea to use buildForm(), which acts in a form route as a controller from which you can return a redirect response:

  public function buildForm(array $form, FormStateInterface $form_state) {
    if (...) {
      $this->messenger()->addMessage('Fee already paid or no fee to pay.');
      return $this->redirect('<front>');

    // build form if fee is not paid already


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.