symfony/translation · error · InvalidResourceException
Unable to load " ".
Error message
Unable to load "%s".
What it means
XmlUtils::loadFile() validates the QT TS file against its DTD/schema; failures surface as InvalidArgumentException which the loader re-wraps as InvalidResourceException('Unable to load "<file>".'). The XML is unreadable, malformed, or fails QT's DTD validation.
Solutions
- Validate the XML independently: `xmllint --noout file.ts` to see the precise parse error and line.
- Fix the malformed XML (unclosed tags, bad entities, encoding declaration).
- Confirm the file is actually a QT TS file, not another XML dialect renamed to .ts.
- Re-export the .ts from Qt Linguist / lupdate; if DTD fetching is blocked, allow local DTD access or use a fully offline-valid file.
- Check the previous exception in the chain (InvalidArgumentException) for the underlying libxml message.
Example fix
// before (messages.ts) <?xml version="1.0"?> <TS><context><name>app</name> // unclosed tags // after <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.0"><context><name>app</name></context></TS>
Defensive patterns
Strategy: try-catch
Validate before calling
libxml_use_internal_errors(true);
$dom = new \DOMDocument();
if (!$dom->load($resource)) {
$err = libxml_get_last_error();
throw new \RuntimeException(sprintf('%s is not valid XML: %s at line %d', $resource, trim($err->message), $err->line));
}
libxml_clear_errors(); Try / catch
try {
$catalogue = $loader->load($resource, $locale);
} catch (InvalidResourceException $e) {
error_log('QT XML load failed: '.$e->getMessage().' previous: '.$e->getPrevious()?->getMessage());
$catalogue = new MessageCatalogue($locale);
} Prevention
- Run xmllint --noout against .ts files in CI
- Re-export .ts files from lupdate/Qt Linguist instead of hand-editing
- Always inspect getPrevious() for the underlying libxml message
- Ensure correct UTF-8 encoding declarations in XML headers
When it happens
Trigger: load() on a .ts file that is not well-formed XML, has wrong encoding, is an HTML/other-XML file misnamed .ts, or violates the QT translation DTD — raised in testLoad paths.
Common situations: Truncated downloads of .ts files, editors saving with wrong encoding, manually edited XML introducing syntax errors, DTD unreachable when validating against remote entities in air-gapped environments.
Related errors
- Error parsing JSON:
- Loading translations from the QT format requires the…
- This is not a local file
- File " " not found.
- Unable to load
AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15).
Data as JSON: /api/errors/9cb616cd267baf4e.
Report an issue: GitHub.
Appendix: source
Thrown at Loader/QtFileLoader.php:45
{
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) {
$translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue;
if ($translationValue) {
$catalogue->set(
(string) $translation->getElementsByTagName('source')->item(0)->nodeValue,
$translationValue,View on GitHub (pinned to ae9e8a51bc)