---
title: "Extbase configuration reference"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:extbase-typoscript-configuration@main"
source: "ExtensionArchitecture/Extbase/Configuration/Reference.rst"
rendered: "2026-09-17T18:20:57+00:00"
---

# Extbase configuration reference {#extbase-configuration-reference-1}

Most Extbase plugin configuration is written in TypoScript. Some of
these settings are read by the Extbase framework itself — they tell Extbase where to
find templates, which pages to read records from, and how to behave when an
action cannot be resolved. Other configuration will be your own,
application-specific, settings that you read inside controllers and Fluid templates.
There are two other configuration "blocks" described on this
page are *not* TypoScript: values that an editor feeds in through FlexForms, and
installation-wide feature toggles.

This page is the working reference for configuration blocks used by Extbase
extensions in practice. For an exhaustive list of TypoScript properties
including data type and default value, see the
[plugin reference in the TypoScript Reference](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/TopLevelObjects/Plugin.html#setup-plugin-extbase).
For the bigger picture of configuration "surfaces" and what belongs in them, see
[Configure Extbase plugins and modules](https://docs.typo3.org/permalink/t3coreapi:extbase-configuration@main).

**On this page**

-   [Where Extbase TypoScript lives](https://docs.typo3.org/permalink/t3coreapi:where-extbase-typoscript-lives@main)
-   [The global scope: config.tx_extbase](https://docs.typo3.org/permalink/t3coreapi:the-global-scope-config-tx-extbase@main)
-   [Custom settings: the settings block](https://docs.typo3.org/permalink/t3coreapi:custom-settings-the-settings-block@main)
-   [Persistence: storage pages and new-record locations](https://docs.typo3.org/permalink/t3coreapi:persistence-storage-pages-and-new-record-locations@main)
-   [View: template, partial and layout paths](https://docs.typo3.org/permalink/t3coreapi:view-template-partial-and-layout-paths@main)
-   [MVC error handling: the mvc block](https://docs.typo3.org/permalink/t3coreapi:mvc-error-handling-the-mvc-block@main)
-   [Output format, language overrides and FlexForm handling](https://docs.typo3.org/permalink/t3coreapi:output-format-language-overrides-and-flexform-handling@main)
-   [Extbase feature toggles (not TypoScript)](https://docs.typo3.org/permalink/t3coreapi:extbase-feature-toggles-not-typoscript@main)

## Where Extbase TypoScript lives {#where-extbase-typoscript-lives}

When you register a plugin using
`\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin()`, Extbase
creates a configuration object in the TypoScript tree. The position in the tree
depends on the extension key and the plugin name.

Settings for **all an extension's plugins** go below
`plugin.tx_<extensionkey>`. The extension key is written without
underscores. For an extension with the key `EXT:my_extension` this will be
`plugin.tx_myextension`.

Settings for **single specific plugins** go below
`plugin.tx_<extensionkey>_<pluginname>`, for example
`plugin.tx_myextension_conferencelist`. Values set here override the
extension-wide values from `plugin.tx_myextension`.

[Backend modules](https://docs.typo3.org/permalink/t3coreapi:backend-modules-api@main) use the same pattern below
`module.tx_<extensionkey>` and
`module.tx_<extensionkey>_<modulename>`.

A few framework settings can also be set globally for every Extbase plugin and
module below `config.tx_extbase`. Use this scope sparingly —
plugin-specific configuration is almost always clearer. See
[The global scope: config.tx_extbase](https://docs.typo3.org/permalink/t3coreapi:extbase-configuration-typoscript-global-scope@main).

The merge order, from lowest to highest precedence, is:

1.  `config.tx_extbase` (global)
1.  `plugin.tx_myextension` (extension-wide)
1.  `plugin.tx_myextension_conferencelist` (plugin-specific)
1.  [FlexForm](https://docs.typo3.org/permalink/t3coreapi:flexforms@main) values set by the editor in the content
    element

FlexForm values therefore take precedence over TypoScript, field by field. A field
that an editor leaves blank can still override the matching TypoScript default with its empty
value; `ignoreFlexFormSettingsIfEmpty` (see
[Output format, language overrides and FlexForm handling](https://docs.typo3.org/permalink/t3coreapi:extbase-configuration-typoscript-other@main)) will retain the TypoScript value.

> [!TIP]
> All the TypoScript examples on this page use the
> [site set](https://docs.typo3.org/permalink/t3coreapi:site-sets@main) file
> [`EXT:my_extension/Configuration/Sets/MyExtension/setup.typoscript`](../../FileStructure/Configuration/Sets/Index.md#file-set-setup-typoscript),
> which is loaded automatically when the set is active. Projects that do not
> use site sets can contain the same TypoScript in an included
> `setup.typoscript` file instead.

## The global scope: `config.tx_extbase` {#the-global-scope-config-tx-extbase}

The `config.tx_extbase` block is the only scope that is **not** bound
to a single extension. Everything below `plugin.tx_myextension` and
`plugin.tx_myextension_pluginname` configures one extension or one
plugin; values placed below `config.tx_extbase` apply to **every
Extbase plugin and module in the frontend**, no matter which extension ships
them. It is the lowest-precedence layer in the merge order above, so any
extension- or plugin-level value overrides it.

Only the **framework** sub-keys are meaningful here — these are the ones read by Extbase itself
to steer control flow, namely `mvc` (error handling) and
`persistence` (class-to-table mapping). The `settings`
and `view` blocks are inherently application-specific: a global
`settings` value would leak into every third-party plugin, and
template paths only make sense for individual extensions. Do not put either there.

> [!WARNING]
> Use this scope sparingly. Values set here will change the behaviour of plugins
> that you did not write — every installed
> Extbase extension — and will do so via a global block that the extension maintainers
> have no reason to inspect. Plugin-specific configuration is self-documenting;
> global configuration acts at a distance. Use
> `config.tx_extbase` if you have a deliberate **installation-wide
> policy**. Use per-plugin configuration in every other case. A global
> value placed in this scope by mistake is a documented pitfall — see
> [A global config.tx_extbase value breaks an unrelated plugin](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-pitfalls-global-config@main).

A legitimate case is a policy that must hold even for plugins that you do not
control. A good example is MVC error handling: "on this site, *any*
Extbase action that cannot be resolved returns 404 rather than silently
falling back to a default action". Setting this once globally is more robust than
hoping that every installed extension has configured it.

**EXT:my_sitepackage/Configuration/Sets/MySitepackage/setup.typoscript**

```typoscript
# Site-wide policy: an unresolvable Extbase action is a 404 everywhere,
# for every plugin on the installation — including third-party ones.
config.tx_extbase.mvc {
    throwPageNotFoundExceptionIfActionCantBeResolved = 1
    showPageNotFoundIfTargetNotFoundException = 1
    showPageNotFoundIfRequiredArgumentIsMissingException = 1
}

```

A single plugin can still opt out by overriding the same key under its own
`plugin.tx_<extensionkey>_<pluginname>.mvc` because plugin scope
takes precedence over the global scope.

## Custom settings: the `settings` block {#custom-settings-the-settings-block}

The `settings` configuration block contains your own configuration
values — everything from "how many items per page" to default values for business
logic. Extbase makes these available in two places:

-   In controllers in the array `$this->settings`
-   In every Fluid template in the `{settings}` variable

**EXT:my_extension/Configuration/Sets/MyExtension/setup.typoscript**

```typoscript
plugin.tx_myextension {
    settings {
        itemsPerPage = 10
        archive {
            showInSidebar = 1
        }
    }
}

```

The nested value above is read in a controller as
`$this->settings['itemsPerPage']` and
`$this->settings['archive']['showInSidebar']`, and in Fluid as
`{settings.itemsPerPage}` and `{settings.archive.showInSidebar}`.

Settings defined for a specific plugin override the extension-wide ones of the
same name, and an editor can override individual settings for a content element
through the relevant plugin's FlexForm.

### "Feeding" settings from a content block FlexForm {#feeding-settings-from-a-content-block-flexform}

Content elements built using Content Blocks and that render an Extbase plugin can
pass or "feed" values to `$this->settings` — without you having to write a FlexForm
data structure by hand. This is a little-known but practical trick, and it
is becoming more relevant as Content Block technology moves into the Core.

The mechanism is as follows: when a content block reuses the `pi_flexform` field and
defines a FlexForm field whose identifier is `settings.<name>`, that value
is merged into `$this->settings['<name>']` exactly like a TypoScript-defined
setting. The same applies to the reusable `pages` and `recursive`
fields, which feed `persistence.storagePid` and
`persistence.recursive`.

**EXT:my_extension/ContentBlocks/ContentElements/conference-list/config.yaml**

```yaml
name: my-vendor/conference-list
group: default
prefixFields: true
prefixType: vendor
fields:
  - identifier: TYPO3/Header
    type: Basic
  # Reuse the existing pages + recursive fields: they feed
  # persistence.storagePid and persistence.recursive
  - identifier: pages
    useExistingField: true
  - identifier: recursive
    useExistingField: true
  # Reuse pi_flexform: any field named settings.* folds into $this->settings
  - identifier: pi_flexform
    type: FlexForm
    useExistingField: true
    fields:
      - identifier: settings.itemsPerPage
        type: Number

```

There are two important things here:

1.  The content block renders through an
    [EXTBASEPLUGIN](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/ContentObjects/Extbaseplugin/Index.html#cobj-extbaseplugin) (Content Blocks provides
    the rendering definition; you only need to set the `pluginName`).
1.  Because the element renders as an Extbase plugin **and** has a
    `pi_flexform` value, Extbase's normal FlexForm-to-settings merge applies.

The editor now sees an "Items per page" field in the content element, and the
controller reads it as `$this->settings['itemsPerPage']` — no custom
FlexForm XML is required.

> [!NOTE]
> **See also**
>
> [Create Extbase plugins (Content Blocks documentation)](https://docs.typo3.org/p/friendsoftypo3/content-blocks/main/en-us/Guides/CreateExtbasePlugin/Index.html#create-extbase-plugin)
> — how to register an Extbase plugin as a content block.

## Persistence: storage pages and new-record locations {#persistence-storage-pages-and-new-record-locations}

The `persistence` block controls where Extbase reads records from
and where it writes new ones.

**EXT:my_extension/Configuration/Sets/MyExtension/setup.typoscript**

```typoscript
plugin.tx_myextension {
    persistence {
        # Read records from pages 42 and 43 ...
        storagePid = 42,43
        # ... and from four levels of subpages below them
        recursive = 4

        classes {
            # New conferences are written to page 50
            MyVendor\MyExtension\Domain\Model\Conference {
                newRecordStoragePid = 50
            }
            # New speakers are written to a separate folder, page 51
            MyVendor\MyExtension\Domain\Model\Speaker {
                newRecordStoragePid = 51
            }
        }
    }
}

```

-   **`storagePid`**

    A comma-separated list of page IDs. Repository read queries return records
    **only** from these pages.

-   **`recursive`**

    The number of subpage levels below each `storagePid` that are
    also searched. The default `0` means only the listed pages themselves are searched.

-   **`classes.<FQCN>.newRecordStoragePid`**

    The page ID where new records of a given domain class are stored when the
    repository persists them. Without it, new records are written to the first
    configured `storagePid`. The key is the fully-qualified class
    name of the [domain model](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-model@main). Because the key is
    based on the class, different models can be stored in different folders — for example
    new `Conference` records can be stored on one page and new
    `Speaker` records on another, as shown above.

-   **`enableAutomaticCacheClearing`**

    Enabled by default. When Extbase persists a change, it clears the page cache
    for the affected records automatically. See
    [Caching for Extbase plugins](https://docs.typo3.org/permalink/t3coreapi:extbase-caching-overview@main) for when and why you might disable this.

> [!NOTE]
> **See also**
>
> -   [The storagePid: where Extbase looks for records](https://docs.typo3.org/permalink/t3coreapi:extbase-concepts-persistence-storagepid@main) — the full
>     `storagePid` resolution rules, and how to disable
>     storage-page filtering.
> -   [findAll() returns nothing on an Extbase repository](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-pitfalls-storagepid@main) — why a repository query
>     returns nothing when a storage page is misconfigured.

## View: template, partial and layout paths {#view-template-partial-and-layout-paths}

The `view` block tells Extbase where to look for Fluid templates,
partials and layouts. Each one is an **array** of paths. A site package can
override an extension's templates without touching the extension itself.

**EXT:my_sitepackage/Configuration/Sets/MySitepackage/setup.typoscript**

```typoscript
plugin.tx_myextension {
    view {
        // combined path configuration for sitepackage and extension - the higher
        // index is red first and falls back to the lower if no template gets found
        templateRootPaths {
            10 = EXT:my_extension/Resources/Private/Extensions/MyExtension/Templates/
            20 = EXT:my_sitepackage/Resources/Private/Extensions/MyExtension/Templates/
        }
        partialRootPaths {
            10 = EXT:my_extension/Resources/Private/Extensions/MyExtension/Partials/
            20 = EXT:my_sitepackage/Resources/Private/Extensions/MyExtension/Partials/
        }
        // sitepackage does not provide any layouts, so here the extension is the only
        // source to look up
        layoutRootPaths {
            10 = EXT:my_extension/Resources/Private/Extensions/MyExtension/Layouts/
        }
    }
}

```

### The default paths and how overriding works {#the-default-paths-and-how-overriding-works}

At render time,
`ActionController` adds the
the resource directories in an extension to the configured paths as defaults:

-   `EXT:my_extension/Resources/Private/Templates/`
-   `EXT:my_extension/Resources/Private/Partials/`
-   `EXT:my_extension/Resources/Private/Layouts/`

The default is added at the **front** of the array, where it acts as the
lowest-priority entry. Fluid resolves paths by **highest numeric key first** and
uses the first matching file it finds. The three cases below show what
Extbase ends up looking at for templates. These implicit additions are not shown in the
**TypoScript -> Active TypoScript** Backend Module.

**Case 1 — no** `view.templateRootPaths` **configured.** The default
is the only path:

**Paths Fluid searches (highest key first)**

```text
EXT:my_extension/Resources/Private/Templates/
```

**Case 2 — an override added under a high key.** This is the usual sitepackage
override:

**EXT:my_sitepackage/Configuration/Sets/MySitepackage/setup.typoscript**

```typoscript
plugin.tx_myextension.view.templateRootPaths.10 = EXT:my_sitepackage/Resources/Private/Extensions/MyExtension/Templates/
```

**Paths Fluid searches (highest key first)**

```text
10  EXT:my_sitepackage/.../Templates/               <- checked first
    EXT:my_extension/Resources/Private/Templates/   (prepended default)
```

Fluid uses your sitepackage template if the file exists there, and otherwise
falls back to the extension's own template. Your override does not have to be
complete — only the templates you actually want to change need to exist.

**Case 3 — the default moved to a different priority.** List the default path
explicitly under a key of your choice. An explicitly listed default keeps the
position you give it instead of being prepended:

**EXT:my_sitepackage/Configuration/Sets/MySitepackage/setup.typoscript**

```typoscript
plugin.tx_myextension.view.templateRootPaths {
  10 = EXT:my_extension/Resources/Private/Templates/
  20 = EXT:my_sitepackage/Resources/Private/Extensions/MyExtension/Templates/
}

```

**Paths Fluid searches (highest key first)**

```text
20  EXT:my_sitepackage/.../Templates/        <- checked first
10  EXT:my_extension/Resources/Private/Templates/
```

The same prepend-and-override behaviour applies to
`partialRootPaths` and `layoutRootPaths`.

### Sharing an argument namespace between plugins {#sharing-an-argument-namespace-between-plugins}

By default every plugin has its own argument namespace: the
`tx_<extensionkey>_<pluginname>[...]` prefix on request arguments and form
fields, for example `tx_myextension_conferencelist[conference]=5`. This
isolation is deliberate — two plugins on the same page will not collide.

`view.pluginNamespace` overrides that prefix. It has two distinct
uses:

1.  **Shorten the prefix** for tidier URLs:

    **EXT:my_extension/Configuration/Sets/MyExtension/setup.typoscript**

    ```typoscript
    plugin.tx_myextension_conferencelist.view.pluginNamespace = conf
    ```

    Arguments are now `conf[conference]=5` instead of the long default.
1.  **Deliberately share a namespace between two plugins** so that one plugin can
    read the other's arguments. Point both plugins at the **same**
    `pluginNamespace`:

    **EXT:my_extension/Configuration/Sets/MyExtension/setup.typoscript**

    ```typoscript
    plugin.tx_myextension_conferencelist.view.pluginNamespace = conf
    plugin.tx_myextension_conferencefilter.view.pluginNamespace = conf
    ```

    A filter plugin and a list plugin sharing the `conf` namespace can now
    act on the same arguments — the filter's form submits values that the list
    plugin reads without the list plugin having to know the filter's plugin
    name. This is the recommended way to make separate plugins cooperate; do not
    try to read another plugin's default namespace by guessing its prefix.

    > [!WARNING]
    > Only share a namespace if you intend this. If two unrelated plugins end up with
    > the same namespace by accident, their arguments will overwrite each other.

    See [Generating URLs with the UriBuilder](https://docs.typo3.org/permalink/t3coreapi:extbase-routing-uri-builder@main) for how namespaces affects
    generated URIs.

## MVC error handling: the `mvc` block {#mvc-error-handling-the-mvc-block}

The `mvc` block controls what Extbase does when a request cannot be
dispatched to a valid action. There are two separate failure stages, and the
settings fall into two corresponding pairs. All accept a boolean (`0` or `1`)
and can be set per plugin or globally in `config.tx_extbase`.

**Stage 1 — the requested action does not exist**

These two settings apply when the request asks for an action that is **not registered**
for the plugin at all (a typo in the URL, an action that has been removed, a manipulated
request). They are mutually exclusive so you should choose only one:

-   **`callDefaultActionIfActionCantBeResolved`**

    Silently fall back to the plugin's first registered action instead of
    failing. The visitor sees the default action's output. Use this when an
    unknown action should degrade gracefully to a sensible default view.

-   **`throwPageNotFoundExceptionIfActionCantBeResolved`**

    Show a "page not found" (HTTP 404) response instead. Use this when an unknown
    action should look like a missing page to visitors and search engines rather
    than silently showing something else.

**Stage 2 — the action exists, but argument mapping fails**

The action is valid, but Extbase cannot build its arguments. This happens during
**argument mapping**, after the action has been resolved, and is handled by
`ActionController::handleArgumentMappingExceptions()`. The two triggers are
different:

-   **`showPageNotFoundIfTargetNotFoundException`**

    The argument references a domain object that **no longer exists** — for
    example `?tx_myextension_conferencelist[conference]=999` where
    conference 999 was deleted. Without this setting Extbase throws a
    `\TYPO3\CMS\Extbase\Property\Exception\TargetNotFoundException`; with it,
    the 404 page is shown. This is the typical "linked record was deleted" case.

-   **`showPageNotFoundIfRequiredArgumentIsMissingException`**

    A **required** argument is absent — the URL omits an argument that the
    action declares as mandatory. Without this setting, Extbase throws a
    `\TYPO3\CMS\Extbase\Mvc\Exception\RequiredArgumentMissingException`; with
    it, the 404 page is shown.

For behaviour beyond "show the 404 page", for example, logging, redirects, custom error
views, override `handleArgumentMappingExceptions()` in your controller. The
default implementation is in
`ActionController`; copy its
signature and inspect the passed `\Exception` to decide what to do.

**EXT:my_extension/Configuration/Sets/MyExtension/setup.typoscript**

```typoscript
plugin.tx_myextension {
  mvc {
    throwPageNotFoundExceptionIfActionCantBeResolved = 1
    showPageNotFoundIfTargetNotFoundException = 1
    showPageNotFoundIfRequiredArgumentIsMissingException = 1
  }
}

```

## Output format, language overrides and FlexForm handling {#output-format-language-overrides-and-flexform-handling}

-   **format**

    -   *Type:* string
    -   *Default:* html

    Sets the default template file format which determines the template file
    extension that Extbase looks for. Prefer a dedicated action per output format
    rather than switching `format` globally — separate actions keep
    responsibility for each format in the controller where it is easy to find.

-   **`_LOCAL_LANG`**

    Overrides individual translation labels of a plugin without editing its XLF
    files. The key is the language key (`default` or an ISO 639-1 code) followed
    by the translation-unit ID:

    **EXT:my_extension/Configuration/Sets/MyExtension/setup.typoscript**

    ```typoscript
    plugin.tx_myextension_conferencelist._LOCAL_LANG.default.list.heading = Upcoming conferences
    plugin.tx_myextension_conferencelist._LOCAL_LANG.de.list.heading = Kommende Konferenzen
    ```

-   **`ignoreFlexFormSettingsIfEmpty`**

    A comma-separated list of FlexForm field names whose empty values should
    **not** override the TypoScript settings of the same name. Because FlexForm
    values take precedence over TypoScript, a field that an editor leaves blank would
    otherwise overrule a TypoScript default with its empty value; listing the
    field here will keep the TypoScript value if the field is left blank. The
    PSR-14 [BeforeFlexFormConfigurationOverrideEvent](https://docs.typo3.org/permalink/t3coreapi:beforeflexformconfigurationoverrideevent@main) allows further
    adjustment of the merged configuration.

> [!NOTE]
> **See also**
>
> [A blank FlexForm field silently overrides the TypoScript default](https://docs.typo3.org/permalink/t3coreapi:extbase-appendix-pitfalls-flexform-empty-overrides@main)
> — the pitfall that this setting prevents with a worked example.

## Extbase feature toggles (not TypoScript) {#extbase-feature-toggles-not-typoscript}

Two Extbase behaviours are controlled by global
[feature toggles](https://docs.typo3.org/permalink/t3coreapi:feature-toggles@main) rather than by TypoScript. They are set in
`$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']` (configured through
[`settings.php`](../../../Configuration/Typo3ConfVars/Index.md#file-project-config-system-settings-php) or the **Settings > Feature Toggles** backend
module) and apply to a whole installation rather than to a single plugin.

-   **`extbase.consistentDateTimeHandling`**

    Enabled by default. Aligns Extbase's `\DateTime` mapping with the FormEngine
    and DataHandler so that timezones and integer-based time fields behave
    consistently across the backend and Extbase. See
    [Consistent DateTime handling](https://docs.typo3.org/permalink/t3coreapi:extbase-domain-property-types-datetime-consistency@main).

-   **`extbase.enableHistoryTracking`**

    Disabled by default (added in TYPO3 v14.2). When enabled, changes persisted by Extbase
    are recorded in `sys_history` and shown in the backend record
    history, similar to backend edits. The toggle enables tracking for all
    Extbase tables; single tables can opt out via TCA using
    `'ctrl' => ['extbase' => ['enableHistoryTracking' => false]]`. Mind the
    GDPR implications — full data snapshots are stored. See
    [Feature #107289](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.2/Feature-107289-AutomaticHistoryTrackingForExtbaseEntities.html#feature-107289-1734172800) and
    [Check relevant feature toggle defaults after upgrading (TYPO3 v14)](https://docs.typo3.org/permalink/t3coreapi:extbase-upgrading-feature-toggle-defaults@main).

> [!NOTE]
> **See also**
>
> -   [plugin reference (TypoScript Reference)](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/TopLevelObjects/Plugin.html#setup-plugin-extbase)
>     — the complete list of Extbase plugin properties with data types and defaults.
> -   [The storagePid: where Extbase looks for records](https://docs.typo3.org/permalink/t3coreapi:extbase-concepts-persistence-storagepid@main) — how `storagePid`
>     and `recursive` are resolved, and how to bypass storage-page
>     filtering.
> -   [View layer in Extbase](https://docs.typo3.org/permalink/t3coreapi:extbase-view-overview@main) — how template path configuration is used
>     during rendering.

Now that you have configured your plugin, you can move on to writing queries, relations and
templates that will turn these settings into a working extension. Start with
[Persistence layer in Extbase](https://docs.typo3.org/permalink/t3coreapi:extbase-persistence-overview@main) for data considerations and
[View layer in Extbase](https://docs.typo3.org/permalink/t3coreapi:extbase-view-overview@main) for output.
