symfony/symfony · error · InvalidArgumentException
The configured log file "%s" is not writeable.
Error message
The configured log file "%s" is not writeable.
What it means
Thrown during DeprecationErrorHandler::displayDeprecations (InvalidArgumentException, line 309) at test-suite shutdown. When SYMFONY_DEPRECATIONS_HELPER contains a 'logFile' query parameter, the handler tries fopen($logFile, 'a'); if that returns false (file/dir not writable, path doesn't exist, permissions), it throws with the offending path. This fires at shutdown, so it appears after the test run rather than at boot.
Source
Thrown at src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php:309
if (!self::hasColorSupport()) {
return $str;
}
$color = $red ? '41;37' : '43;30';
return "\x1B[{$color}m{$str}\x1B[0m";
}
/**
* @param string[] $groups
*/
private function displayDeprecations(array $groups, Configuration $configuration): void
{
$cmp = static fn ($a, $b) => $b->count() - $a->count();
if ($configuration->shouldWriteToLogFile()) {
if (false === $handle = @fopen($file = $configuration->getLogFile(), 'a')) {
throw new \InvalidArgumentException(\sprintf('The configured log file "%s" is not writeable.', $file));
}
} else {
$handle = fopen('php://output', 'w');
}
foreach ($groups as $group) {
if ($this->deprecationGroups[$group]->count()) {
$deprecationGroupMessage = \sprintf(
'%s deprecation notices (%d)',
\in_array($group, ['direct', 'indirect', 'self'], true) ? "Remaining $group" : ucfirst($group),
$this->deprecationGroups[$group]->count()
);
if ($configuration->shouldWriteToLogFile()) {
fwrite($handle, "\n$deprecationGroupMessage\n");
} else {
fwrite($handle, "\n".self::colorize($deprecationGroupMessage, 'legacy' !== $group && 'indirect' !== $group)."\n");
}
View on GitHub (pinned to 698e28026c)
Solutions
- Point logFile at a directory the test process can write (e.g. var/log/, build/logs/, or %kernel.cache_dir%).
- Create the parent directory and fix permissions: mkdir -p var/log && chmod a+w var/log.
- Use an absolute path you control; remove logFile from SYMFONY_DEPRECATIONS_HELPER to fall back to stdout (php://output).
Example fix
# before SYMFONY_DEPRECATIONS_HELPER=max[total]=0&logFile=/var/log/deprecations.log # after (writable project dir, ensure it exists) mkdir -p var/log SYMFONY_DEPRECATIONS_HELPER=max[total]=0&logFile=%kernel.project_dir%/var/log/deprecations.log
Defensive patterns
Strategy: validation
Validate before calling
$logFile = $_ENV['SYMFONY_DEPRECATIONS_HELPER_LOG'] ?? null;
if ($logFile !== null) {
$dir = dirname($logFile);
if (!is_dir($dir) || !is_writable($dir)) {
throw new \RuntimeException('logFile dir not writable: '.$dir);
}
} Type guard
function logFileIsWritable(?string $path): bool {
if ($path === null) return true;
$dir = realpath(dirname($path));
return $dir !== false && is_dir($dir) && is_writable($dir);
} Try / catch
try {
// run phpunit with logFile set
} catch (\InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'is not writeable')) {
// fall back to stdout by removing logFile from SYMFONY_DEPRECATIONS_HELPER
putenv('SYMFONY_DEPRECATIONS_HELPER='.preg_replace('/&?logFile=[^&]*/', '', getenv('SYMFONY_DEPRECATIONS_HELPER')));
}
throw $e;
} Prevention
- Use a project-local dir (var/log) created by your build, not a system path.
- Add a CI step that mkdir -p the log dir before phpunit.
- Verify is_writable(dirname($logFile)) at boot, not at shutdown.
When it happens
Trigger: Setting SYMFONY_DEPRECATIONS_HELPER=max[total]=0&logFile=/var/log/symfony-deprecations.log where /var/log isn't writable by the test runner, or the logFile path's parent directory doesn't exist. Triggered when displayDeprecations() runs (shutdown handler) and the deprecation report is configured for file output.
Common situations: CI running as an unprivileged user pointing logFile at a system dir; relative path resolved against an unexpected cwd; container where the mounted volume is read-only; path with a missing intermediate directory (fopen can't create dirs).
Related errors
- The ignoreFile "%s" does not exist.
- The baselineFile "%s" does not exist.
- Unable to write in the "%s" directory.
- Cannot read font file "%s".
- Failed to write file "%s".
AI-assisted analysis of symfony/symfony@698e28026c (2026-08-06).
Data as JSON: /api/errors/a6e45f2596bee18c.
Report an issue: GitHub.