sebastianbergmann/phpunit · error · CannotWriteBaselineException

Cannot write baseline to "%s".

Error message

Cannot write baseline to "%s".

What it means

A baseline write was requested (--generate-baseline, or Writer::write() called from a run) but the directory that would contain the file does not exist: realpath(dirname($baselineFile)) failed or the result is not a directory. Only the parent directory is verified — the file itself is then written with file_put_contents.

Source

Thrown at src/Runner/Baseline/Writer.php:36

/**
 * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
 *
 * @internal This class is not covered by the backward compatibility promise for PHPUnit
 */
final readonly class Writer
{
    /**
     * @param non-empty-string $baselineFile
     *
     * @throws CannotWriteBaselineException
     */
    public function write(string $baselineFile, Baseline $baseline): void
    {
        $normalizedBaselineFile = realpath(dirname($baselineFile));

        if ($normalizedBaselineFile === false || !is_dir($normalizedBaselineFile)) {
            throw new CannotWriteBaselineException(sprintf('Cannot write baseline to "%s".', $baselineFile));
        }

        $pathCalculator = new RelativePathCalculator($normalizedBaselineFile);

        $writer = new XMLWriter;

        $writer->openMemory();
        $writer->setIndent(true);
        $writer->startDocument();

        $writer->startElement('files');
        $writer->writeAttribute('version', (string) Baseline::VERSION);

        foreach ($baseline->groupedByFileAndLine() as $file => $lines) {
            $writer->startElement('file');
            $writer->writeAttribute('path', $pathCalculator->calculate($file));

            foreach ($lines as $line => $issues) {

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Create the parent directory first: mkdir -p build (or commit a .gitkeep inside it).
  2. Fix the path passed to --generate-baseline so every directory component exists.
  3. If calling Writer::write() programmatically, ensure dirname($baselineFile) passes realpath() and is_dir() first.

Example fix

# before
vendor/bin/phpunit --generate-baseline=build/baseline.xml  # build/ missing

# after
mkdir -p build
vendor/bin/phpunit --generate-baseline=build/baseline.xml
Defensive patterns

Strategy: validation

Validate before calling

// Before --generate-baseline / Writer::write()
$dir = dirname($baselineFile);
if (!is_dir($dir) && !mkdir($dir, 0777, true) && !is_dir($dir)) {
    throw new RuntimeException("Cannot create baseline directory {$dir}");
}

Prevention

When it happens

Trigger: vendor/bin/phpunit --generate-baseline=build/baseline.xml when build/ does not exist; a path through a missing intermediate directory; dirname resolving to an existing file; a symlink whose target does not exist so realpath() fails.

Common situations: Fresh clones without build artifacts; CI jobs assuming a directory created by an earlier step; refactoring output paths; typo in the target path.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/91622f8b5d2c9e7a. Report an issue: GitHub.