---
title: "Validation in Extbase"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extbase-validation-why@main"
source: "ExtensionArchitecture/Extbase/Validation/Index.rst"
rendered: "2026-09-21T11:24:09+00:00"
---

# Validation in Extbase {#extbase-validation-why}

Extbase validates incoming request arguments automatically before your action
method is called. If validation fails, the framework calls
`errorAction()` instead of the intended action. Use
`#[IgnoreValidation]` on a parameter to let an action receive an object
even if it is invalid — for example to redisplay a form with its errors.

Validators can be Extbase built-ins, custom classes, or — since TYPO3 v14 —
[Symfony constraints](https://docs.typo3.org/permalink/t3coreapi:extbase-validation-symfony-constraints@main).

**On this page**

-   [Where validation fits into the Extbase request lifecycle](https://docs.typo3.org/permalink/t3coreapi:where-validation-fits-into-the-extbase-request-lifecycle@main)
-   [Where to declare validators](https://docs.typo3.org/permalink/t3coreapi:where-to-declare-validators@main)
-   [Validating Extbase model properties with Symfony constraints](https://docs.typo3.org/permalink/t3coreapi:validating-extbase-model-properties-with-symfony-constraints@main)
-   [Ignoring the validation result with #[IgnoreValidation]](https://docs.typo3.org/permalink/t3coreapi:ignoring-the-validation-result-with-ignorevalidation@main)
-   [Customising errorAction()](https://docs.typo3.org/permalink/t3coreapi:customising-erroraction@main)
-   [Displaying validation errors in Fluid templates](https://docs.typo3.org/permalink/t3coreapi:displaying-validation-errors-in-fluid-templates@main)
-   [What to read next](https://docs.typo3.org/permalink/t3coreapi:what-to-read-next@main)

## Where validation fits into the Extbase request lifecycle {#extbase-validation-when}

The sequence for every request that carries arguments is:

1.  **Property mapping** — everything arriving from the request is a string or
    an array of strings. Property mapping converts these into typed PHP values
    and objects (see [Property mapping: request arguments to objects](https://docs.typo3.org/permalink/t3coreapi:extbase-controller-propertymapping@main)).
1.  **Validation** — the mapped values are checked against any
    `#[Validate]` attributes declared on the action parameter, on the
    domain model property, or both. Property validators run first; action
    parameter validators run afterwards. Either alone is sufficient — both
    can be combined on the same type.
1.  **Action dispatch** — if validation passes, the action method is called
    with the resolved arguments.
1.  **Error handling** — if validation fails, `errorAction()` is called
    instead. The default implementation redirects the user to the referring
    request (typically the action that rendered the form), carrying the
    validation errors so they can be displayed.

This means you declare *what* valid data looks like; Extbase decides *when*
to run the checks and *where* to route the request on failure.

> [!NOTE]
> Validation is not limited to form submissions. It runs on *every* action
> that receives typed arguments including detail, filter, and search
> actions that read their input from URL parameters. A record created in the
> TYPO3 backend may satisfy TCA validation but still fail Extbase model
> validation when the same record is loaded as an action argument in the
> frontend. See [Extbase model validation and TCA validation are independent](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-pitfalls-validation-tca-gap@main) for a
> full explanation.

## Where to declare validators {#extbase-validation-model}

Validators can be declared on action parameters, on domain model properties,
or both.

**On an action parameter** — validates the value passed to an
action before the action runs:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Attribute\Validate;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class ConferenceController extends ActionController
{
  public function createAction(
    #[Validate('NotEmpty')]
    #[Validate('StringLength', options: ['maximum' => 255])]
    string $title,
  ): ResponseInterface {
    // $title is guaranteed non-empty and at most 255 characters
    return $this->htmlResponse();
  }
}

```

**On a domain model property** — validates the property every time the model
is used as an action argument:

**EXT:my_extension/Classes/Domain/Model/Conference.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Model;

use TYPO3\CMS\Extbase\Attribute\Validate;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;

class Conference extends AbstractEntity
{
  #[Validate('NotEmpty')]
  #[Validate('StringLength', options: ['maximum' => 255])]
  protected string $title = '';
}

```

Placing validators on the model above means that every action that receives a
`Conference` argument benefits from the same rules,
without having to repeat the attribute on every parameter.

> [!TIP]
> Validators do not have to live on the persisted domain model. A base model
> can carry no validators at all, while separate
> DTO classes carry different validator sets
> for different use cases — for example a `ConferenceRegistrationForm` DTO
> with strict seat-count validation and a `ConferenceDraftForm` DTO with
> only a title requirement. Each DTO is mapped by property mapping just like
> a domain model and can have its own independent validation rules.

When a form submission fails validation, Extbase re-calls the originating
action (typically `newAction()` or `editAction()`). If that action has the
model as a typed parameter and declares `#[IgnoreValidation]` on it,
the [Form ViewHelper \<f:form>](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Form/Index.html#typo3-fluid-form) view helper can read the submitted
values from the object and [Form.validationResults ViewHelper \<f:form.validationResults>](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Form/ValidationResults.html#typo3-fluid-form-validationresults)
can display the errors inline — the object does not need to be valid for
this to work.

## Validating Extbase model properties with Symfony constraints {#extbase-validation-symfony-constraints}

<!-- TODO: no Markdown rendering for "versionadded" -->

See Feature: #106945 - Allow usage of Symfony validators in Extbase.

Domain model properties also accept the constraint attributes of the
Symfony Validator component, for example `#[Assert\NotBlank]` or
`#[Assert\Iban]`. Extbase runs them like its own validators, so their errors
reach `errorAction()` and the Fluid template in the same way. The package
[`symfony/validator`](https://packagist.org/packages/symfony/validator) is a dependency of Extbase, so there is nothing
to install:

**EXT:my_extension/Classes/Domain/Model/Conference.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Domain\Model;

use Symfony\Component\Validator\Constraints as Assert;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;

class Conference extends AbstractEntity
{
  #[Assert\NotBlank]
  #[Assert\Length(max: 255)]
  protected string $title = '';

  #[Assert\Url(
    message: 'LLL:EXT:my_extension/Resources/Private/Language/errors.xlf:url',
  )]
  protected string $website = '';
}

```

A message that starts with `LLL:` is translated. Placeholders of the Symfony
messages, such as `{{ value }}`, are passed to the translation as `%1$s`,
`%2$s` and so on.

Symfony constraints only work on model properties, not on action parameters.
Constraints that depend on the Symfony framework, such as `#[Assert\File]`
and `#[Assert\Image]`, are not supported yet.

## Ignoring the validation result with `#[IgnoreValidation]` {#extbase-validation-ignore}

Sometimes you need to receive an object without running its validators, for
example when displaying a "new" form that is pre-populated from a submitted but
invalid object, or when an action intentionally accepts a partially filled
model.

Place `#[IgnoreValidation]` on the parameter to tell Extbase to ignore
the validation result for that argument and dispatch the action regardless:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use MyVendor\MyExtension\Domain\Model\Conference;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Attribute\IgnoreValidation;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class ConferenceController extends ActionController
{
  public function newAction(
    #[IgnoreValidation]
    ?Conference $conference = null,
  ): ResponseInterface {
    $this->view->assign('conference', $conference ?? new Conference());
    return $this->htmlResponse();
  }
}

```

Validation still runs — `#[IgnoreValidation]` does not skip it. It
instructs Extbase to call the action even when the argument is invalid.
This is what allows `newAction()` to receive a partially filled
`Conference` back from a failed `createAction()` and hand it to
the template so `f:form` can redisplay the submitted values with inline
errors.

Without `#[IgnoreValidation]`, the framework would see the invalid
`Conference`, call `errorAction()`, which redirects back to
`newAction()`, which would validate again — an infinite cycle.

## Customising `errorAction()` {#extbase-error-action-howto}

The built-in `errorAction()` adds a generic [flash message](https://docs.typo3.org/permalink/t3coreapi:flash-messages@main) and redirects the user to the referring request. For most contact or registration forms this
is sufficient.

To show a custom error flash message, override `getErrorFlashMessage()`:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
protected function getErrorFlashMessage(): bool|string
{
    return 'Please correct the errors in the form before saving.';
}
```

Return `false` to suppress the flash message.

To completely change how validation errors are handled — for example to return
a JSON response — override
`errorAction()` itself:

**EXT:my_extension/Classes/Controller/ConferenceController.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;

class ConferenceController extends ActionController
{
  protected function errorAction(): ResponseInterface
  {
    $errors = $this->arguments->validate();
    // Choose the status code appropriate for your API,
    // 422 and 400 are both common choices
    return $this->jsonResponse(json_encode([
      'errors' => $this->flattenErrors($errors),
    ]))->withStatus(422);
  }
}

```

## Displaying validation errors in Fluid templates {#extbase-validation-fluid}

Extbase makes validation errors available in Fluid via the
`f:form.validationResults` view helper. Wrap form fields with it to show
per-field error messages:

**EXT:my_extension/Resources/Private/Templates/Conference/New.fluid.html**

```html
<f:form action="create" name="conference" object="{conference}">
    <f:form.validationResults for="conference.title">
        <f:for each="{validationResults.errors}" as="error">
            <p class="error">{error.message}</p>
        </f:for>
    </f:form.validationResults>
    <f:form.textfield property="title" />
    <f:form.submit value="Save" />
</f:form>
```

The `for` attribute is the dot-notation path to the validated object or
property. Leave it empty to access all errors in the current request.

## What to read next {#extbase-validation-next}

-   [Built-in validators and the #\[Validate\] attribute](https://docs.typo3.org/permalink/t3coreapi:extbase-validation-builtin@main) — the full list of validators that ship
    with Extbase and their configuration options.
-   [Writing a custom Extbase validator](https://docs.typo3.org/permalink/t3coreapi:extbase-validation-custom@main) — how to write a validator for domain
    rules that the built-in validators cannot express.
-   [Property mapping: request arguments to objects](https://docs.typo3.org/permalink/t3coreapi:extbase-controller-propertymapping@main) — how request data is mapped to objects
    before validation runs.
