symfony/translation · error · RuntimeException

No loader is registered for the

Error message

No loader is registered for the "%s" format.

What it means

Same code path as the previous RuntimeException in Translator, thrown when the missing-loader resource is not a string (e.g. an array or object resource), so no resource path can be shown; only the format is reported.

Solutions

  1. Register a loader for that format before adding resources
  2. Verify resource definitions use formats with available loaders
  3. Check container DI wiring for translation loader tags (translation.loader)

Example fix

// before
$translator->addResource('csv', $resourceArray, 'fr'); // no csv loader
// after
$translator->addLoader('csv', new CsvFileLoader());
$translator->addResource('csv', $resourceArray, 'fr');
Defensive patterns

Strategy: try-catch

Validate before calling

$format = $resource[0];
if (!isset($loaders[$format])) {
    throw new \RuntimeException("Loader for format '{$format}' is not registered.");
}

Try / catch

try {
    $translator->getCatalogue($locale);
} catch (RuntimeException $e) {
    if (str_contains($e->getMessage(), 'No loader is registered')) {
        // add the loader for the reported format
    }
}

Prevention

When it happens

Trigger: A resource added with a non-string second argument (array/object loader payload) whose format key has no registered loader.

Common situations: Custom loader/resource pairs where addLoader() was skipped, or resources defined in config with formats whose loaders are not compiled into the container.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15). Data as JSON: /api/errors/50468c34185baf17. Report an issue: GitHub.

Appendix: source

Thrown at Translator.php:374

    {
        return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('xxh128', serialize($this->cacheVary), true)), 0, 7), '/', '_').'.php';
    }

    /**
     * @internal
     */
    protected function doLoadCatalogue(string $locale): void
    {
        $this->catalogues[$locale] = new MessageCatalogue($locale);

        if (isset($this->resources[$locale])) {
            foreach ($this->resources[$locale] as $resource) {
                if (!isset($this->loaders[$resource[0]])) {
                    if (\is_string($resource[1])) {
                        throw new RuntimeException(\sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
                    }

                    throw new RuntimeException(\sprintf('No loader is registered for the "%s" format.', $resource[0]));
                }
                $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
            }
        }
    }

    private function loadFallbackCatalogues(string $locale): void
    {
        $current = $this->catalogues[$locale];

        foreach ($this->computeFallbackLocales($locale) as $fallback) {
            if (!isset($this->catalogues[$fallback])) {
                $this->initializeCatalogue($fallback);
            }

            $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
            foreach ($this->catalogues[$fallback]->getResources() as $resource) {
                $fallbackCatalogue->addResource($resource);

View on GitHub (pinned to ae9e8a51bc)