symfony/translation · error · NotFoundResourceException

Error opening file " ".

Error message

Error opening file "%s".

What it means

CsvFileLoader::loadResource() opens the CSV translation file with fopen(); when fopen() fails (returns false, error suppressed with @) it throws NotFoundResourceException. This means the resource path/stream passed to load() could not be opened for reading.

Solutions

  1. Verify the resource path exists with file_exists($resource) before loading and fix the path.
  2. Check file read permissions for the PHP process user (e.g. chmod/chown on the translations directory).
  3. Ensure the file is actually a readable regular file, not a directory or broken symlink.
  4. Catch NotFoundResourceException in your loader/translation-container setup and fail gracefully or fall back to an empty catalogue.

Example fix

// before
$loader->load('trans/messages.csv', 'en');
// after
$path = __DIR__.'/translations/messages.en.csv';
if (!is_file($path) || !is_readable($path)) {
    throw new \RuntimeException("CSV translation file missing or unreadable: $path");
}
$loader->load($path, 'en');
Defensive patterns

Strategy: validation

Validate before calling

$path = $resource;
if (!is_string($path) || !is_file($path) || !is_readable($path)) {
    throw new \InvalidArgumentException("Unreadable CSV translation file: $path");
}

Type guard

function isReadableFile(mixed $r): bool { return is_string($r) && is_file($r) && is_readable($r); }

Try / catch

try {
    $catalogue = $loader->load($path, 'en');
} catch (Symfony\Component\Translation\Exception\NotFoundResourceException $e) {
    $catalogue = new MessageCatalogue('en'); // fallback
}

Prevention

When it happens

Trigger: Calling CsvFileLoader::load($resource, $locale, $domain) with a path that does not exist, has wrong read permissions, is a directory, or an unreadable stream (fopen returns false).

Common situations: Typo in the translation file path, missing '%kernel.project_dir%/translations' prefix, file not deployed to the server, wrong permissions after container build, or passing a URL/stream wrapper fopen cannot open.

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/2a73dd5909494a60. Report an issue: GitHub.

Appendix: source

Thrown at Loader/CsvFileLoader.php:31

use Symfony\Component\Translation\Exception\NotFoundResourceException;

/**
 * CsvFileLoader loads translations from CSV files.
 *
 * @author Saša Stamenković <umpirsky@gmail.com>
 */
class CsvFileLoader extends FileLoader
{
    private string $delimiter = ';';
    private string $enclosure = '"';

    protected function loadResource(string $resource): array
    {
        $messages = [];

        if (!$file = @fopen($resource, 'r')) {
            throw new NotFoundResourceException(\sprintf('Error opening file "%s".', $resource));
        }

        try {
            while (false !== $data = fgetcsv($file, null, $this->delimiter, $this->enclosure, '')) {
                // empty lines are read as [null]
                if (isset($data[1]) && 2 === \count($data) && !str_starts_with($data[0], '#')) {
                    $messages[$data[0]] = $data[1];
                }
            }
        } finally {
            fclose($file);
        }

        return $messages;
    }

    /**
     * Sets the delimiter and enclosure character for CSV.

View on GitHub (pinned to ae9e8a51bc)