symfony/translation · error · UnexpectedValueException
" " defined in translator.paths does not exist or is not a…
Error message
"%s" defined in translator.paths does not exist or is not a directory.
What it means
During DI extension loading, TranslationBundle validates each entry of the translator.paths config with $container->fileExists(). If a configured path does not exist or is not a directory, it throws UnexpectedValueException naming the offending path.
Solutions
- Create the missing directory (mkdir -p) or commit it with a .gitkeep
- Fix the path in translator.paths config (typos, wrong kernel.project_dir reference)
- Remove the stale path entry from the config
Example fix
# before (translator.yaml)
translator:
paths:
- '%kernel.project_dir%/translations/custom'
# after — either create the dir:
# mkdir -p translations/custom && touch translations/custom/.gitkeep
# or fix the path:
translator:
paths:
- '%kernel.project_dir%/translations' Defensive patterns
Strategy: validation
Validate before calling
foreach ($config['paths'] as $dir) {
if (!is_dir($dir)) {
throw new \UnexpectedValueException("translator.paths entry missing: $dir");
}
} Type guard
function isTranslationDir(string $dir): bool {
return is_dir($dir);
} Try / catch
try {
$kernel->boot();
} catch (\UnexpectedValueException $e) {
if (str_contains($e->getMessage(), 'translator.paths')) {
// fix config or create directory, then clear cache
}
throw $e;
} Prevention
- Commit translation directories to VCS (add .gitkeep)
- Validate configured paths in CI before deployment
- Avoid referencing symlinks/mounts that may be absent in production
- Clear the container cache after changing translator.paths
When it happens
Trigger: config/packages/translator.yaml contains translator.paths: ['%kernel.project_dir%/translations/custom'] but that directory was never created or was renamed/deleted; a path pointing to a file instead of a directory; cache warmup after a partial deploy.
Common situations: New project scaffold where the custom translations dir isn't committed to git; symlinked deployment where the path is missing in production; typo in the configured path.
Related errors
- Missing required option
- The scheme "null" is not supported by this provider.
- Provider " " not found. Available: " ".
- The scheme is not supported by any provider.
- The " ()" method cannot be called as the wrapped translator…
AI-assisted analysis of symfony/translation@ae9e8a51bc (2026-09-15).
Data as JSON: /api/errors/f13bc64800cd3475.
Report an issue: GitHub.
Appendix: source
Thrown at TranslationBundle.php:306
$r = new \ReflectionClass(AuthenticationException::class);
$dirs[] = $transPaths[] = \dirname($r->getFileName(), 2).'/Resources/translations';
}
$parameterBag = $container->getParameterBag();
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
$bundlePath = $parameterBag->unescapeValue($bundle['path']);
if ($container->fileExists($dir = $bundlePath.'/Resources/translations') || $container->fileExists($dir = $bundlePath.'/translations')) {
$dirs[] = $transPaths[] = $dir;
} else {
$nonExistingDirs[] = $dir;
}
}
foreach ($config['paths'] as $dir) {
if (!$container->fileExists($dir)) {
throw new \UnexpectedValueException(\sprintf('"%s" defined in translator.paths does not exist or is not a directory.', $dir));
}
$dirs[] = $transPaths[] = $dir;
}
// the parameter bag returns paths in their escaped form, the filesystem needs the literal one
$defaultDir = $parameterBag->unescapeValue($parameterBag->resolveValue($config['default_path']));
if (null === $defaultDir) {
// allow null
} elseif ($container->fileExists($defaultDir)) {
$dirs[] = $defaultDir;
} else {
$nonExistingDirs[] = $defaultDir;
}
return [$dirs, $transPaths, $nonExistingDirs];
}View on GitHub (pinned to ae9e8a51bc)