---
title: "Breaking: #110702 - Widened FAL processing task interfaces"
manual: "TYPO3 Core Changelog"
version: "main"
permalink: "https://docs.typo3.org/permalink/changelog:breaking-110702-1789915156"
source: "Changelog/15.0/Breaking-110702-WidenedFalProcessingTaskInterfaces.rst"
typo3-version: "15.0"
typo3-major: 15
type: "breaking"
issue: 110702
forge: "https://forge.typo3.org/issues/110702"
tags: ["FAL", "PHP-API", "TypoScript", "NotScanned", "ext:core"]
rendered: "2026-10-27T20:58:30+00:00"
---

# Breaking: #110702 - Widened FAL processing task interfaces {#breaking-110702-1789915156}

See [forge#110702](https://forge.typo3.org/issues/110702)

## Description {#description}

TYPO3's File Abstraction Layer (FAL) processing pipeline - the
`\TYPO3\CMS\Core\Resource\Processing\TaskInterface`/`AbstractTask`/`ProcessorInterface`/
`\TYPO3\CMS\Core\Resource\Processing\ProcessorRegistry`/`\TYPO3\CMS\Core\Resource\Service\FileProcessingService` classes that resize,
crop and convert images - has so far only ever operated on FAL files
(`\TYPO3\CMS\Core\Resource\File` and
`\TYPO3\CMS\Core\Resource\ProcessedFile`). The same pipeline now also
processes resources that are not backed by FAL - most commonly a system
resource shipped with a package and referenced via an `EXT:`/`PKG:`
identifier - by routing a `\TYPO3\CMS\Core\Resource\ProcessedFile`, or the new
`\TYPO3\CMS\Core\Resource\ProcessedResource`, through the same task/
processor machinery (see [Feature: #110702 - Process system resource images](https://docs.typo3.org/permalink/changelog:feature-110702-1789927725)). Several
signatures widened for this:

-   `\TYPO3\CMS\Core\Resource\Processing\TaskInterface::getSourceFile()` now returns
    `\TYPO3\CMS\Core\SystemResource\Type\SystemResourceInterface`
    instead of `\TYPO3\CMS\Core\Resource\File`.
-   `\TYPO3\CMS\Core\Resource\Processing\TaskInterface::getTargetFile()` now returns the new
    `\TYPO3\CMS\Core\Resource\ProcessedResourceInterface` instead of
    `\TYPO3\CMS\Core\Resource\ProcessedFile`. `\TYPO3\CMS\Core\Resource\ProcessedFile` now
    implements this new interface, alongside the new
    `\TYPO3\CMS\Core\Resource\ProcessedResource` for the non-FAL case.
-   `AbstractTask::__construct()` and
    `\TYPO3\CMS\Core\Resource\Processing\TaskTypeRegistry::getTaskForType()` now take a
    `\TYPO3\CMS\Core\Resource\ProcessedResourceInterface` instead of a `\TYPO3\CMS\Core\Resource\ProcessedFile`, and
    the `AbstractTask::$sourceFile` property is now typed
    `\TYPO3\CMS\Core\SystemResource\Type\SystemResourceInterface` instead of `\TYPO3\CMS\Core\Resource\File`. A custom task class
    registered for a task type is constructed with a `\TYPO3\CMS\Core\Resource\ProcessedResource`
    when the source is a system resource.
-   `\TYPO3\CMS\Core\Resource\Processing\ProcessorRegistry` no longer offers a task whose source is not a FAL
    `\TYPO3\CMS\Core\Resource\File` to a processor unless that processor implements the new,
    opt-in `\TYPO3\CMS\Core\Resource\Processing\ResourceAwareProcessorInterface`
    marker. TYPO3 Core's `\TYPO3\CMS\Core\Resource\Processing\LocalImageProcessor` and `\TYPO3\CMS\Core\Resource\Processing\SvgImageProcessor`
    now implement it and handle a non-FAL source for the
    `Image.CropScaleMask` task; no other Core processor does. As with any
    interface, a subclass inherits it: a custom processor extending
    `\TYPO3\CMS\Core\Resource\Processing\LocalImageProcessor` or `\TYPO3\CMS\Core\Resource\Processing\SvgImageProcessor` is offered non-FAL
    tasks as well.
-   `\TYPO3\CMS\Core\Resource\Service\FileProcessingService` has a new, last constructor argument
    `\TYPO3\CMS\Core\Resource\ProcessedResourceCache`.
-   `\TYPO3\CMS\Core\Resource\Service\FileProcessingService::processFile()` now accepts
    `File|FileReference|SystemResourceInterface` (was
    `File|FileReference`), returns `ProcessedFile|ProcessedResource`
    (was `\TYPO3\CMS\Core\Resource\ProcessedFile`), and its `$driver` parameter is now
    nullable - a non-FAL resource is never fetched through a
    `\TYPO3\CMS\Core\Resource\ResourceStorage` driver in the first place, so there is none to pass.
-   `\TYPO3\CMS\Core\Resource\Event\BeforeFileProcessingEvent`/`\TYPO3\CMS\Core\Resource\Event\AfterFileProcessingEvent` widen the
    same way: `getDriver()` now returns `?DriverInterface`,
    `getFile()` returns `FileInterface|SystemResourceInterface`, and
    `getProcessedFile()`/`setProcessedFile()` use
    `\TYPO3\CMS\Core\Resource\ProcessedResourceInterface`.
-   `\TYPO3\CMS\Core\Imaging\ImageResource::getOriginalFile()` now
    returns `File|SystemResourceInterface|null` (was `?File`), and
    `\TYPO3\CMS\Core\Imaging\ImageResource::getProcessedFile()` now returns
    `?ProcessedResourceInterface` (was `?ProcessedFile`). The
    corresponding `with*()` methods and the constructor accept the same
    wider types. An image resource of a processed system resource carries the
    system resource and its `\TYPO3\CMS\Core\Resource\ProcessedResource`.

The URLs of `EXT:`/`PKG:` images rendered through image
processing change as well:

-   A processed variant is no longer stored in
    `typo3temp/assets/_processed_/` as
    `csm_<name>_<hash>.<extension>`, but in
    `typo3temp/assets/images/system/<hash>/<hash>-<hash>.<extension>`.
-   An image that does not need processing is linked by its own public URL,
    as generated by the system resource publisher - including its cache
    busting query string, for example `logo.png?1791262813`.
-   The link generated by `imageLinkWrap` for such an image passes
    the system resource identifier as `file` parameter to the
    `tx_cms_showpic` eID, instead of the uid of a `sys_file` record.

## Impact {#impact}

Custom `ProcessorInterface`/`\TYPO3\CMS\Core\Resource\Processing\TaskInterface`/`AbstractTask`
implementations, or PSR-14 listeners of the two events above, that use
`getSourceFile()`/`getTargetFile()`/`getFile()`/
`getProcessedFile()`/`getDriver()` as a concrete
`\TYPO3\CMS\Core\Resource\File`/`\TYPO3\CMS\Core\Resource\ProcessedFile`/`\TYPO3\CMS\Core\Resource\Driver\DriverInterface` without a type check
\- for example calling `getUid()`, `getForLocalProcessing()`,
`getStorage()` or any `\TYPO3\CMS\Core\Resource\Driver\DriverInterface` method directly - will
fail static analysis against the wider declared type, and can now
genuinely receive a system resource, or a `null` driver, at runtime:
a template or content element that references an `EXT:`/`PKG:`
image is processed through this same pipeline starting with this release.

Custom task classes that type-hint the constructor argument as
`\TYPO3\CMS\Core\Resource\ProcessedFile`, or assign a `\TYPO3\CMS\Core\Resource\File` to `$sourceFile`, fail
with a PHP fatal error. Code that instantiates
`\TYPO3\CMS\Core\Resource\Service\FileProcessingService` manually, or extends it with its own
constructor, fails with an `ArgumentCountError`. Code relying on
`\TYPO3\CMS\Core\Imaging\ImageResource::getOriginalFile()`/`getProcessedFile()` returning a
FAL object fails for an `EXT:`/`PKG:` image.

Tests, caches, CDN or proxy rules and other code that relied on the
previous URL pattern of processed `EXT:`/`PKG:` images no longer
match.

## Affected installations {#affected-installations}

Installations with extensions that implement `ProcessorInterface`
directly, subclass `\TYPO3\CMS\Core\Resource\Processing\LocalImageProcessor`/`\TYPO3\CMS\Core\Resource\Processing\SvgImageProcessor`,
`AbstractTask` or `\TYPO3\CMS\Core\Resource\Service\FileProcessingService`, listen to
`\TYPO3\CMS\Core\Resource\Event\BeforeFileProcessingEvent`/`\TYPO3\CMS\Core\Resource\Event\AfterFileProcessingEvent`, or use
`\TYPO3\CMS\Core\Imaging\ImageResource::getOriginalFile()`/`getProcessedFile()`, and rely
on the narrower pre-existing types without narrowing themselves.

Installations that depend on the URL of a processed `EXT:`/`PKG:`
image.

## Migration {#migration}

Narrow the type before using `\TYPO3\CMS\Core\Resource\File`/`\TYPO3\CMS\Core\Resource\ProcessedFile`/
`\TYPO3\CMS\Core\Resource\Driver\DriverInterface`-specific members, the same way TYPO3 Core's own
processors do now:

**EXT:my_extension/Classes/Resource/Processing/MyProcessor.php**

```php
use TYPO3\CMS\Core\Resource\File;

public function processTask(TaskInterface $task): void
{
    $sourceFile = $task->getSourceFile();
    if (!$sourceFile instanceof File) {
        throw new \InvalidArgumentException('MyProcessor can only process a FAL File.', 1234567890);
    }
    // $sourceFile is now a concrete File again.
}
```

**EXT:my_extension/Classes/EventListener/MyFileProcessingListener.php**

```php
public function __invoke(AfterFileProcessingEvent $event): void
{
    $driver = $event->getDriver();
    if ($driver === null) {
        // A non-FAL resource - nothing to do here, or handle it explicitly.
        return;
    }
    // $driver is now a concrete DriverInterface again.
}
```

Custom task classes declare the constructor argument as
`\TYPO3\CMS\Core\Resource\ProcessedResourceInterface`, the same as `AbstractTask` does.

A subclass of `\TYPO3\CMS\Core\Resource\Processing\LocalImageProcessor` or `\TYPO3\CMS\Core\Resource\Processing\SvgImageProcessor` that
should only handle FAL files declines other tasks in
`canProcessTask()`:

**EXT:my_extension/Classes/Resource/Processing/MyImageProcessor.php**

```php
use TYPO3\CMS\Core\Resource\File;

public function canProcessTask(TaskInterface $task): bool
{
    return $task->getSourceFile() instanceof File
        && parent::canProcessTask($task);
}
```

Code that instantiates `\TYPO3\CMS\Core\Resource\Service\FileProcessingService` itself retrieves it
through dependency injection instead.

Check `\TYPO3\CMS\Core\Imaging\ImageResource::getOriginalFile()`/`getProcessedFile()` for
`\TYPO3\CMS\Core\Resource\File`/`\TYPO3\CMS\Core\Resource\ProcessedFile` before using FAL-specific methods.

Do not rely on the file name or location of a processed image.
