---
title: "Upgrading from older Extbase versions"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extbase-upgrading@main"
source: "ExtensionArchitecture/Extbase/Appendix/Upgrading.rst"
rendered: "2026-09-22T15:26:06+00:00"
---

# Upgrading from older Extbase versions {#extbase-upgrading}

This page lists breaking changes and migration steps for
upgrading an Extbase extension to a newer TYPO3 version. Each entry details
what has changed, which version introduced the change, and what to do.

> [!TIP]
> Many migrations can be automated, and TYPO3 Rector ([`ssch/typo3-rector`](https://packagist.org/packages/ssch/typo3-rector)) provides
> rules to do so. The tool is actively maintained and updated for each TYPO3 version that is
> released.

**On this page**

-   [Annotations replaced by PHP attributes (TYPO3 v12 / required from v14)](https://docs.typo3.org/permalink/t3coreapi:annotations-replaced-by-php-attributes-typo3-v12-required-from-v14@main)
-   [Attribute namespace moved from annotation to attribute (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:attribute-namespace-moved-from-annotation-to-attribute-typo3-v14@main)
-   [Attribute array syntax deprecated (TYPO3 v14, removed in v15)](https://docs.typo3.org/permalink/t3coreapi:attribute-array-syntax-deprecated-typo3-v14-removed-in-v15@main)
-   [#[FileUpload] array syntax replaced by named arguments (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:fileupload-array-syntax-replaced-by-named-arguments-typo3-v14@main)
-   [#[Validate] and #[IgnoreValidation] moved to parameter level (TYPO3 v14, removed in v15)](https://docs.typo3.org/permalink/t3coreapi:validate-and-ignorevalidation-moved-to-parameter-level-typo3-v14-removed-in-v15@main)
-   [Magic findBy(), `findOneBy`(), countBy*() methods removed (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:magic-findby-findoneby-countby-methods-removed-typo3-v14@main)
-   [StandaloneView removed (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:standaloneview-removed-typo3-v14@main)
-   [list_type plugin removed; fifth parameter of configurePlugin() restricted (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:list-type-plugin-removed-fifth-parameter-of-configureplugin-restricted-typo3-v14@main)
-   [Translation domain syntax as shorter alternative to LLL:EXT: (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:translation-domain-syntax-as-shorter-alternative-to-lll-ext-typo3-v14@main)
-   [Check relevant feature toggle defaults after upgrading (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:check-relevant-feature-toggle-defaults-after-upgrading-typo3-v14@main)

## Annotations replaced by PHP attributes (TYPO3 v12 / required from v14) {#extbase-annotation-migration}

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

DocBlock annotation support was fully removed. Extbase ignores annotations
silently — no error is thrown.

Native PHP attributes (introduced in PHP 8.0) replace the Doctrine-based
DocBlock annotation syntax. Extbase has supported PHP attributes since
TYPO3 v12. In TYPO3 v14 the annotation syntax was removed entirely.

| Old annotation (removed in v14) | New PHP attribute |
| --- | --- |
| `@ExtbaseORMLazy` | `#[Lazy]` |
| `@ExtbaseORMCascade("remove")` | `#[Cascade('remove')]` |
| `@ExtbaseORMTransient` | `#[Transient]` |
| `@ExtbaseValidate(...)` | `#[Validate(...)]` |
| `@ExtbaseIgnoreValidation` | `#[IgnoreValidation]` |

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

```diff
 use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
+use TYPO3\CMS\Extbase\Attribute\ORM\Lazy;
 use TYPO3\CMS\Extbase\Persistence\ObjectStorage;

 class Entity extends AbstractEntity
 {
-    /**
-     * @var ObjectStorage<ChildEntity>
-     * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
-     */
+    #[Lazy]
     protected ObjectStorage $property;
 }
```

> [!NOTE]
> **See also**
>
> -   [ExtbaseAnnotationToAttributeRector](https://github.com/sabbelasichon/typo3-rector/blob/main/docs/all_rectors_overview.md#extbaseannotationtoattributerector)

## Attribute namespace moved from annotation to attribute (TYPO3 v14) {#extbase-upgrading-attribute-namespace}

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

The namespace \TYPO3\CMS\Extbase\Annotation is deprecated. Class
aliases remain available in v14 but will be removed in v15. Update your
use statements to \TYPO3\CMS\Extbase\Attribute when dropping
TYPO3 v13 support.

All Extbase attributes have been moved from `\TYPO3\CMS\Extbase\Annotation` to
`\TYPO3\CMS\Extbase\Attribute`.

## Attribute array syntax deprecated (TYPO3 v14, removed in v15) {#extbase-attributes-migration-config-array}

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

Passing a configuration array as the first argument to Extbase attributes
is deprecated (Deprecation #97559).
The array-based syntax still works in v14 but will be removed in v15.

| Old array syntax (deprecated in v14) | New named-argument syntax |
| --- | --- |
| `#[Cascade(['value' => 'remove'])]` | `#[Cascade('remove')]` |
| `#[Validate(['validator' => 'NotEmpty'])]` | `#[Validate('NotEmpty')]` |

> [!IMPORTANT]
> There is **no attribute syntax that is compatible with both TYPO3 v13 and
> v14**. PHP attributes are parsed statically and cannot be conditionally
> defined based on the TYPO3 version. Extensions supporting both versions in
> the same release must keep the array-based syntax and accept the deprecation
> warning in v14.

> [!NOTE]
> **See also**
>
> [MigratePassingAnArrayOfConfigurationValuesToExtbaseAttributesRector](https://github.com/sabbelasichon/typo3-rector/blob/main/docs/all_rectors_overview.md#migratepassinganarrayofconfigurationvaluestoextbaseattributesrector)

## `#[FileUpload]` array syntax replaced by named arguments (TYPO3 v14) {#extbase-fileupload-attribute-migration}

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

The array-based configuration syntax for #[FileUpload] is deprecated
and will be removed in TYPO3 v15. Replace the array with named arguments.

In TYPO3 v13, `#[FileUpload]` accepted a single configuration array. In
v14 the attribute requires named arguments instead:

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

```diff
-#[FileUpload([
-    'validation' => [
-        'required' => true,
-        'maxFiles' => 1,
-        'fileSize' => ['minimum' => '10K', 'maximum' => '2M'],
-        'mimeType' => ['allowedMimeTypes' => ['image/jpeg', 'image/png']],
-        'fileExtension' => ['allowedFileExtensions' => ['jpg', 'jpeg', 'png']],
-    ],
-    'uploadFolder' => '1:/user_upload/conference_logos/',
-])]
+#[FileUpload(
+    validation: [
+        'required' => true,
+        'maxFiles' => 1,
+        'fileSize' => ['minimum' => '10K', 'maximum' => '2M'],
+        'mimeType' => ['allowedMimeTypes' => ['image/jpeg', 'image/png']],
+        'fileExtension' => ['allowedFileExtensions' => ['jpg', 'jpeg', 'png']],
+    ],
+    uploadFolder: '1:/user_upload/conference_logos/',
+)]
 protected ?FileReference $logo = null;
```

> [!IMPORTANT]
> There is **no syntax that is not deprecated in either TYPO3 v13 or v14**.
> Extensions that support both versions in the same release must keep the
> array-based syntax and accept the deprecation warning in v14.

> [!NOTE]
> **See also**
>
> -   [File uploads in Extbase domain models](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-fileupload@main) — full reference for the `#[FileUpload]`
>     attribute and its named arguments.

## `#[Validate]` and `#[IgnoreValidation]` moved to parameter level (TYPO3 v14, removed in v15) {#extbase-validation-migration}

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

Placing #[Validate] and #[IgnoreValidation] on the action
method with a named $param / $argumentName property is
deprecated and will be removed in TYPO3 v15.

Before TYPO3 v14, PHP attributes could only be attached to methods, so both
attributes required a named property to identify which parameter they targeted.
TYPO3 v14 introduced support for placing attributes directly on the parameter,
meaning you can now position the attribute on the parameter itself:

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

```diff
-#[Validate(param: 'conference', validator: 'NotEmpty')]
-#[IgnoreValidation(argumentName: 'conference')]
 public function editAction(
+    #[Validate(validator: 'NotEmpty')]
+    #[IgnoreValidation]
     Conference $conference,
 ): ResponseInterface {
 }
```

> [!NOTE]
> **See also**
>
> [Deprecation #108227](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.0/Deprecation-108227-UsageOfIgnoreValidationAndValidateAttributesForParametersAtMethodLevel.html#deprecation-108227-1763668119)
> — full deprecation details and automated migration via Rector.

## Magic `findBy`*(), \`findOneBy\`*(), `countBy`\*() methods removed (TYPO3 v14) {#extbase-upgrading-magic-findby}

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

Magic property-name methods were deprecated in TYPO3 v12.3 and removed in
v14. Replace them with the explicit array-based signatures.

| Old (removed in v14) | New |
| --- | --- |
| `findByTitle($value)` | `findBy(['title' => $value])` |
| `findOneByTitle($value)` | `findOneBy(['title' => $value])` |
| `countByTitle($value)` | `count(['title' => $value])` |

`findByUid()` and `findByIdentifier()` are not affected and remain
available.

> [!NOTE]
> **See also**
>
> [Migration](https://docs.typo3.org/m/typo3/reference-coreapi/13.4/en-us/ExtensionArchitecture/Extbase/Reference/Domain/Repository/Index.html#extbase-repository-find-by-magic-migration) — the
> migration guide in the TYPO3 v13 branch of this manual.

## `StandaloneView` removed (TYPO3 v14) {#extbase-upgrading-standalone-view}

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

\TYPO3\CMS\Fluid\View\StandaloneView was deprecated in TYPO3 v13
and removed in v14. The replacement is
ViewFactoryInterface together with
ViewFactoryData.

`StandaloneView` was the historical way to render a Fluid template outside
of a controller, for example, inside a service class, a scheduler task, or an email
renderer. It is no longer available.

The new way injects `ViewFactoryInterface`
and creates a view by passing a
`ViewFactoryData` value object:

**EXT:my_extension/Classes/Service/MailService.php**

```php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Service;

use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\View\ViewFactoryData;
use TYPO3\CMS\Core\View\ViewFactoryInterface;

readonly class MailService
{
  public function __construct(
    protected ViewFactoryInterface $viewFactory,
  ) {}

  public function renderTemplate(ServerRequestInterface $request): string
  {
    $view = $this->viewFactory->create(new ViewFactoryData(
      templateRootPaths: ['EXT:my_extension/Resources/Private/Templates/'],
      partialRootPaths: ['EXT:my_extension/Resources/Private/Partials/'],
      layoutRootPaths: ['EXT:my_extension/Resources/Private/Layouts/'],
      request: $request,
    ));
    $view->assign('data', $this->loadData());
    return $view->render('Mail/Notification');
  }
}

```

Pass the current `ServerRequestInterface` wherever possible. The view
factory uses it for request-aware rendering (language, base URI, etc.).

> [!NOTE]
> **See also**
>
> -   [Deprecation: #104773 — Custom Fluid views and Extbase](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/13.3/Deprecation-104773-CustomFluidViewsAndExtbase.html#deprecation-104773-1724942036)
>     changelog entry with full migration notes.

## list_type plugin removed; fifth parameter of `configurePlugin()` restricted (TYPO3 v14) {#extbase-upgrading-plugin-list-type}

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

The list_type / "General Plugin" content element was removed. All
plugins must be registered as dedicated CType content elements. The
fifth parameter $pluginType of ExtensionUtility::configurePlugin()
now only accepts 'CType' (or being omitted); any other value throws an
\InvalidArgumentException (Important #105538).

Older extensions could pass
`ExtensionUtility::PLUGIN_TYPE_PLUGIN_LIST` (`'list_type'`) as the
fifth argument, or register their plugin as a `list_type` TCA entry. Both
approaches no longer work in TYPO3 v14.

**What to do:**

-   Remove the fifth argument from `configurePlugin()` or pass
    `ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT`.
-   Provide an upgrade wizard for your extension that extends
    `\TYPO3\CMS\Install\Updates\AbstractListTypeToCTypeUpdate` to migrate
    existing content records from `list_type` to the new `CType`.
    TYPO3 does not ship a wizard for extension-specific plugins. Each extension
    must provide its own
    (see [Deprecation #105076](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/13.4/Deprecation-105076-PluginContentElementAndPluginSubTypes.html#deprecation-105076-1726923626) for a
    reference implementation).

> [!NOTE]
> **See also**
>
> -   [Registering an Extbase frontend plugin](https://docs.typo3.org/permalink/t3coreapi:extbase-registration-frontend-plugin@main)
>     for the current registration approach.
> -   [Plugin registered with list_type no longer works](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-pitfalls-list-type@main)
>     for common pitfalls.

## Translation domain syntax as shorter alternative to LLL:EXT: (TYPO3 v14) {#extbase-upgrading-translation-domain-syntax}

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

A shorter domain-based syntax for label references was introduced as an
alternative to the legacy LLL:EXT: file path syntax
(Feature #93334).

Legacy syntax remains fully supported and is not deprecated. Both forms
resolve to the same translation entries and can be used interchangeably:

| Legacy syntax | Domain syntax (v14+) |
| --- | --- |
| `LLL:EXT:my_ext/Resources/Private/Language/locallang.xlf:key` | `my_ext.messages:key` |
| `LLL:EXT:my_ext/Resources/Private/Language/locallang_db.xlf:key` | `my_ext.db:key` |
| `LLL:EXT:my_ext/Resources/Private/Language/locallang_val.xlf:key` | `my_ext.val:key` |
| `LLL:EXT:my_ext/Resources/Private/Language/Form/locallang.xlf:key` | `my_ext.form.messages:key` |

The domain syntax follows the pattern `extension_key.resource:label_key`.
The resource name is derived from the file name:

-   `locallang.xlf` maps to the fixed resource name `messages`.
-   `locallang_suffix.xlf` strips the `locallang_` prefix, leaving
    `suffix` — so `locallang_db.xlf` becomes `db`.
-   Subdirectories below `Resources/Private/Language/` are prepended as
    dot-separated parts — `Form/locallang.xlf` becomes `form.messages`.

> [!NOTE]
> **See also**
>
> -   [Translation domain mapping for label reference](https://docs.typo3.org/permalink/t3coreapi:label-reference-domain@main) for a full syntax reference and resolution
>     rules including the `language:domain:list` CLI command.

## Check relevant feature toggle defaults after upgrading (TYPO3 v14) {#extbase-upgrading-feature-toggle-defaults}

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

The extbase.consistentDateTimeHandling feature toggle now defaults to
true for new installations
(Important #106467).

Feature toggles behave differently on upgrade than fresh installs: an existing
instance **keeps whatever value it already had**, while a new installation will get
the new default. A toggle whose default changed between versions will therefore
retain the *old* behaviour after an upgrade unless you set it
explicitly. After upgrading to TYPO3 v14 check the values below — the defaults
may not match what your code now expects.

-   **`extbase.consistentDateTimeHandling`**

    Introduced in TYPO3 v13.4 and set to `false` by default; new TYPO3 v14
    installations default to `true`. (TYPO3 v12 did not have this toggle.)

    An instance upgraded from v12 or v13 will keep the `false` setting and will
    continue to use
    the **old** `\DateTime` mapping. Certain functionality is missing
    with the `false` setting: correct timezone-offset handling for native datetime fields,
    named timezones instead of fixed offsets (no daylight-saving shifts), correct
    interpretation of integer-based time fields, and support for `00:00:00` as a
    valid time in nullable fields. Many extensions contain timezone workarounds
    that exist *only* to rectify the old behaviour; enabling the toggle
    lets you remove them. Enable it once you have reviewed your
    `\DateTime` handling:

    **config/system/additional.php**

    ```php
    $GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['extbase.consistentDateTimeHandling'] = true;
    ```

-   **`frontend.cache.autoTagging`**

    Introduced in TYPO3 v13.3 and enabled by default on fresh TYPO3 v14
    installations, but `false` in the shipped default configuration
    ([Feature #104990](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/13.3/Feature-104990-AutomaticFrontendCacheTagging.html#feature-104990-1726495719)).

    An instance upgraded from an earlier version keeps the `false` value and
    therefore gets **no** automatic frontend cache tagging: repository reads no
    longer tag the page cache, so a changed record does not evict the pages that
    display it, and those pages serve stale content until they expire or are
    cleared another way. Extbase's [automatic cache clearing](https://docs.typo3.org/permalink/t3coreapi:extbase-caching-autoclearing@main) still covers records written through a
    repository, but the broad read-side tagging is off. Enable it once you have
    verified your caches invalidate as expected:

    **config/system/additional.php**

    ```php
    $GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['frontend.cache.autoTagging'] = true;
    ```

-   **`extbase.enableHistoryTracking`**

    Added in TYPO3 v14.2 and set to `false` by default, so you won't get
    an upgrade-preservation surprise, but it is worth knowing that it exists. The global
    feature toggle enables history tracking for **all** Extbase domain model
    tables; individual tables can then opt out via TCA with
    `'ctrl' => ['extbase' => ['enableHistoryTracking' => false]]`. Note the
    GDPR implication: full data snapshots are written to `sys_history`, so
    disable it for tables holding sensitive data and prune regularly. See
    [Feature #107289](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.2/Feature-107289-AutomaticHistoryTrackingForExtbaseEntities.html#feature-107289-1734172800).

> [!NOTE]
> **See also**
>
> -   [Consistent DateTime handling](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-property-types-datetime-consistency@main) for the full list of DateTime
>     behaviour activated by the toggle.
> -   [Enabling automatic cache tagging in Extbase](https://docs.typo3.org/permalink/t3coreapi:extbase-caching-cachetags-featureflag@main) for what automatic cache
>     tagging does and how to enable it.
> -   [Feature toggles (TYPO3 Explained)](https://docs.typo3.org/permalink/t3coreapi:feature-toggles@main)
>     for how toggles are stored and edited.
