symfony/translation · error · InvalidResourceException
This is not a local file
Error message
This is not a local file "%s".
What it means
When the XLIFF resource is not an inline XML string, the loader checks stream_is_local(); remote streams (http://, ftp:// wrappers) are rejected with this InvalidResourceException because Symfony only loads translation files from local storage.
Solutions
- Download the XLIFF file to a local path first, then pass the local file path to load().
- Use a stream wrapper that is local (e.g. copy to a temp file with copy() or file_get_contents and pass the XML string directly).
- If passing XML content, ensure it is a string starting with '<?xml' so isXmlString() treats it as inline content.
Example fix
// before
$loader->load('https://cdn.example.com/messages.en.xlf', 'en');
// after
$xml = file_get_contents('https://cdn.example.com/messages.en.xlf');
$loader->load($xml, 'en'); Defensive patterns
Strategy: validation
Validate before calling
if (!is_string($resource) || !str_starts_with(ltrim($resource), '<?xml')) {
if (!stream_is_local($resource)) {
throw new \InvalidArgumentException('Resource must be a local file or an XML string.');
}
} Try / catch
try {
$catalogue = $loader->load($resource, $locale);
} catch (InvalidResourceException $e) {
if (str_contains($e->getMessage(), 'not a local file')) {
$resource = downloadToLocalTemp($resource);
$catalogue = $loader->load($resource, $locale);
}
} Prevention
- Never pass URL stream wrappers as translation resources.
- Resolve env-var-based resource paths at boot and assert they are local paths.
- Fetch remote translations into a local cache directory before loading.
When it happens
Trigger: Passing a URL or remote stream wrapper path as $resource to XliffFileLoader::load(), e.g. 'https://example.com/messages.en.xlf'.
Common situations: Developers pointing the translation loader at a CDN or remote translation service URL; configs built dynamically where the resource comes from an env var containing a URL.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Loading translations from the Xliff format requires the…
- File " " not found.
- This is neither a file nor an XLIFF string
- Unable to load
- Invalid resource provided
AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15).
Data as JSON: /api/errors/c40f164cb575d491.
Report an issue: GitHub.
Appendix: source
Thrown at Loader/XliffFileLoader.php:40
use Symfony\Component\Translation\MessageCatalogueInterface;
use Symfony\Component\Translation\Util\XliffUtils;
/**
* XliffFileLoader loads translations from XLIFF files.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class XliffFileLoader 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 Xliff format requires the Symfony Config component.');
}
if (!$this->isXmlString($resource)) {
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));
}
if (!is_file($resource)) {
throw new InvalidResourceException(\sprintf('This is neither a file nor an XLIFF string "%s".', $resource));
}
}
try {
if ($this->isXmlString($resource)) {
$dom = XmlUtils::parse($resource);
} else {
$dom = XmlUtils::loadFile($resource);
}
} catch (\InvalidArgumentException|XmlParsingException|InvalidXmlException $e) {View on GitHub (pinned to ae9e8a51bc)