symfony/translation · error · NotFoundResourceException

File " " not found.

Error message

File "%s" not found.

What it means

QtFileLoader checks file_exists() after confirming the resource is a local stream; a missing file raises NotFoundResourceException naming the path. This is a distinct, catchable signal that the translation catalogue file simply does not exist.

Solutions

  1. Check the exact path exists: `ls -l <resource>`; watch for case-sensitivity on Linux.
  2. Ensure your build/export step generates .ts files for every supported locale.
  3. Fix the resources path passed to the translator (Translator::addResource or loader config).
  4. Add a existence check with file_exists() before addResource to fail fast with a clearer app-level message.

Example fix

// before
$translator->addResource('qt', '/app/translations/messages.fr.ts', 'fr'); // file absent
// after
$file = '/app/translations/messages.fr.ts';
if (!is_file($file)) {
    throw new \RuntimeException("Translation file missing: $file");
}
$translator->addResource('qt', $file, 'fr');
Defensive patterns

Strategy: validation

Validate before calling

if (!is_file($resource)) {
    throw new \RuntimeException(sprintf('Translation file does not exist: %s (dir listing: %s)', $resource, implode(',', (array) @glob(dirname($resource).'/*'))));
}

Type guard

function fileExistsCaseSensitive(string $path): bool {
    return is_file($path) && basename($path) === basename(glob(dirname($path).'/'.basename($path), GLOB_NOCHECK)[0] ?? $path);
}

Try / catch

try {
    $catalogue = $loader->load($resource, $locale);
} catch (NotFoundResourceException $e) {
    error_log('Missing translation file: '.$e->getMessage());
    $catalogue = new MessageCatalogue($locale); // or fall back to default locale
}

Prevention

When it happens

Trigger: load() with a local path that does not exist — wrong directory in the translator's resource loader config, locale/domain file naming mismatch (e.g. messages.fr.ts absent), file deleted or never deployed.

Common situations: Per-locale files not generated for new languages, .gitignore excluding translation artifacts, path typos or case-sensitivity differences on Linux, container volumes missing the translations directory.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at Loader/QtFileLoader.php:39

/**
 * QtFileLoader loads translations from QT Translations XML files.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
class QtFileLoader implements LoaderInterface
{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        if (!class_exists(XmlUtils::class)) {
            throw new RuntimeException('Loading translations from the QT format requires the Symfony Config component.');
        }

        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
        }

        if (!file_exists($resource)) {
            throw new NotFoundResourceException(\sprintf('File "%s" not found.', $resource));
        }

        try {
            $dom = XmlUtils::loadFile($resource);
        } catch (\InvalidArgumentException $e) {
            throw new InvalidResourceException(\sprintf('Unable to load "%s".', $resource), $e->getCode(), $e);
        }

        $internalErrors = libxml_use_internal_errors(true);
        libxml_clear_errors();

        $xpath = new \DOMXPath($dom);
        $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]');

        $catalogue = new MessageCatalogue($locale);
        if (1 == $nodes->length) {
            $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message');
            foreach ($translations as $translation) {

View on GitHub (pinned to ae9e8a51bc)