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

  1. Create the missing directory (mkdir -p) or commit it with a .gitkeep
  2. Fix the path in translator.paths config (typos, wrong kernel.project_dir reference)
  3. 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

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


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)