symfony/translation · error · InvalidResourceException
Cannot load resource
Error message
Cannot load resource "%s".
What it means
IcuDatFileLoader::load() constructs a \ResourceBundle($locale, $resource); if the bundle cannot be created (null/false returned, caught exception) it throws InvalidResourceException('Cannot load resource...'). The file exists but ResourceBundle could not parse or open it as a valid ICU bundle.
Solutions
- Regenerate the .dat bundle with an ICU version matching your PHP intl extension's ICU.
- Verify the bundle path is the base path ResourceBundle expects (bundles directory pattern).
- Test the bundle directly: new \ResourceBundle($locale, $path) and inspect getErrorCode().
- Confirm the intl extension is installed and its ICU version (php --ri intl) is compatible with the bundle.
Example fix
// before
$rb = new \ResourceBundle('en_FR', '/app/resources/messages'); // bundle has no en_FR
// after
$rb = new \ResourceBundle('fr_FR', '/app/resources/messages');
if (!$rb || intl_is_failure($rb->getErrorCode())) {
throw new \RuntimeException('Invalid ICU bundle: '.$rb?->getErrorMessage());
} Defensive patterns
Strategy: try-catch
Validate before calling
$rb = new \ResourceBundle($locale, $basePath);
if (!$rb || intl_is_failure($rb->getErrorCode())) {
throw new \RuntimeException('Unusable ICU bundle: '.($rb?->getErrorMessage() ?? 'null bundle'));
} Type guard
function isValidResourceBundle(\ResourceBundle $rb): bool { return intl_is_failure($rb->getErrorCode()) === false; } Try / catch
try {
$catalogue = $loader->load($basePath, $locale);
} catch (Symfony\Component\Translation\Exception\InvalidResourceException $e) {
error_log('ICU bundle invalid: '.$e->getMessage());
$catalogue = new MessageCatalogue($locale);
} Prevention
- Compile bundles with an ICU version matching php-intl (check php --ri intl).
- Validate bundles at build time with ResourceBundle directly.
- Never hand-edit or truncate .dat files.
- Test bundle loading in CI on the same intl version as production.
When it happens
Trigger: ResourceBundle constructor returns falsy for an existing but invalid/empty/incompatible .dat bundle, or the bundle lacks the requested locale data and ResourceBundle reports it as missing.
Common situations: Corrupted or truncated .dat file, bundle compiled with an ICU version incompatible with the PHP intl extension, wrong bundle path passed so ResourceBundle finds nothing, or missing intl/icu data.
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
- $rb->getErrorMessage()
- $rb->getErrorMessage()
- Cannot parse message translation: please install the "intl"…
- This is not a local file
- File " " not found.
AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15).
Data as JSON: /api/errors/816b5a9c2f93f85d.
Report an issue: GitHub.
Appendix: source
Thrown at Loader/IcuDatFileLoader.php:43
{
public function load(mixed $resource, string $locale, string $domain = 'messages'): MessageCatalogue
{
if (!stream_is_local($resource.'.dat')) {
throw new InvalidResourceException(\sprintf('This is not a local file "%s".', $resource));
}
if (!file_exists($resource.'.dat')) {
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(FileResource::class)) {
$catalogue->addResource(new FileResource($resource.'.dat'));
}
return $catalogue;
}
}
View on GitHub (pinned to ae9e8a51bc)