symfony/translation · error · InvalidResourceException

Cannot load resource

Error message

Cannot load resource "%s".

What it means

IcuResFileLoader loads translations from compiled ICU .res resource bundles. After constructing a ResourceBundle, it throws InvalidResourceException when the bundle could not be loaded (null/false result), meaning the .res file is missing, corrupt, or not a valid ICU bundle for the requested locale.

Solutions

  1. Verify the .res/.dat resource file exists at the exact path passed to load() and is readable.
  2. Rebuild the ICU resource bundles with msgfmt / genrb for the locales you need.
  3. Confirm the locale string matches the bundle's locale naming; try loading the bundle directly with new ResourceBundle($locale, $resource) to see ICU's error code.
  4. Check the intl/ICU extension version compatibility with the bundle format version.

Example fix

// before
$loader->load('/resources/messages.en.res', 'en'); // file missing
// after
if (!is_file('/resources/messages.en.res')) {
    throw new \RuntimeException('Run genrb to build messages.en.res first');
}
$loader->load('/resources/messages.en.res', 'en');
Defensive patterns

Strategy: validation

Validate before calling

if (!is_file($resource) || !is_readable($resource)) {
    throw new \RuntimeException(sprintf('ICU resource missing or unreadable: %s', $resource));
}
$probe = new \ResourceBundle($locale, $resource);
if (!$probe || intl_is_failure($probe->getErrorCode())) {
    throw new \RuntimeException(sprintf('ICU cannot load bundle: %s', $probe ? $probe->getErrorMessage() : 'null bundle'));
}

Type guard

function isValidIcuBundle(string $locale, string $resource): bool {
    $rb = @new \ResourceBundle($locale, $resource);
    return $rb !== null && !intl_is_failure($rb->getErrorCode());
}

Try / catch

try {
    $catalogue = $loader->load($resource, $locale);
} catch (InvalidResourceException $e) {
    $logger->error('ICU resource load failed', ['resource' => $resource, 'msg' => $e->getMessage()]);
    $catalogue = new MessageCatalogue($locale);
}

Prevention

When it happens

Trigger: Calling load($resource, $locale) where the ResourceBundle constructor returns no usable bundle — the $resource path points to a nonexistent or corrupt .res file, or ICU cannot resolve the bundle for the given locale. Raised in tests testDatEnglishLoad/testDatFrenchLoad paths.

Common situations: Missing .dat/.res translation files after deployment, ICU data not built (packaging steps skipped), wrong resource path or locale naming (e.g. 'en' vs 'en_US'), corrupted bundles from a broken intl build.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at Loader/IcuResFileLoader.php:43

{
    public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
    {
        if (!stream_is_local($resource)) {
            throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
        }

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

        try {
            $rb = new \ResourceBundle($locale, $resource);
        } catch (\Exception) {
            $rb = null;
        }

        if (!$rb) {
            throw new InvalidResourceException(\sprintf('Cannot load resource "%s".', $resource));
        } elseif (intl_is_failure($rb->getErrorCode())) {
            throw new InvalidResourceException($rb->getErrorMessage(), $rb->getErrorCode());
        }

        $messages = $this->flatten($rb);
        $catalogue = new MessageCatalogue($locale);
        $catalogue->add($messages, $domain);

        if (class_exists(DirectoryResource::class)) {
            $catalogue->addResource(new DirectoryResource($resource));
        }

        return $catalogue;
    }

    /**
     * Flattens an ResourceBundle.
     *

View on GitHub (pinned to ae9e8a51bc)