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

  1. Point logFile at a directory the test process can write (e.g. var/log/, build/logs/, or %kernel.cache_dir%).
  2. Create the parent directory and fix permissions: mkdir -p var/log && chmod a+w var/log.
  3. 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

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


AI-assisted analysis of symfony/symfony@698e28026c (2026-08-06). Data as JSON: /api/errors/a6e45f2596bee18c. Report an issue: GitHub.