sebastianbergmann/phpunit · error · PHPUnit\TextUI\RuntimeException

Cannot read from {file}

Error message

Cannot read from {file}

What it means

When you pass --test-id-filter-file, PHPUnit reads one test ID per line from that file to re-run a selected subset of tests (e.g. previously failed ones). TestSuiteFilterProcessor::process() reads the file with @file(); if the read fails it throws RuntimeException('Cannot read from <file>'). It means the file identified by the merged CLI configuration could not be read at all.

Source

Thrown at src/TextUI/TestSuiteFilterProcessor.php:94

                    $configuration->testsUsing(),
                ),
            );
        }

        if ($configuration->hasTestsRequiringPhpExtension()) {
            $factory->addIncludeGroupFilter(
                array_map(
                    Groups::virtualGroupForRequiredPhpExtension(...),
                    $configuration->testsRequiringPhpExtension(),
                ),
            );
        }

        if ($configuration->hasTestIdFilterFile()) {
            $lines = @file($configuration->testIdFilterFile(), FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

            if ($lines === false) {
                throw new RuntimeException('Cannot read from ' . $configuration->testIdFilterFile());
            }

            $testIds = [];

            foreach ($lines as $line) {
                if ($line !== '') {
                    $testIds[] = $line;
                }
            }

            if ($testIds !== []) {
                $factory->addTestIdFilter($testIds);
            }
        }

        if ($configuration->hasTestIdFilter()) {
            $factory->addTestIdFilter([$configuration->testIdFilter()]);
        }

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Verify the file exists and is readable in the exact container/step that runs PHPUnit: `test -r ids.txt`
  2. Regenerate the ID file from its source (for example the recorded failed test IDs) before the run instead of relying on a stale cache
  3. Fix permissions or mounts so the runner user can read the file
  4. Pass a path that is absolute or relative to the directory PHPUnit is invoked from

Example fix

# before
$ vendor/bin/phpunit --test-id-filter-file ids.txt
# RuntimeException: Cannot read from ids.txt

# after
$ test -r ids.txt || regenerate-ids.sh
$ vendor/bin/phpunit --test-id-filter-file "$PWD/ids.txt"
Defensive patterns

Strategy: validation

Validate before calling

$file = 'ids.txt';
if (!is_string($file) || !is_file($file) || !is_readable($file)) {
    throw new RuntimeException("Test ID filter file {$file} is missing or unreadable");
}

Try / catch

try {
    // run phpunit with --test-id-filter-file
} catch (\RuntimeException $e) {
    if (str_starts_with($e->getMessage(), 'Cannot read from ')) {
        // regenerate or fix the ID file, then re-run
    }
}

Prevention

When it happens

Trigger: Running `vendor/bin/phpunit --test-id-filter-file ids.txt` where ids.txt does not exist at run time (deleted after Application's earlier is_file check), is not readable due to permissions, or is outside the paths allowed by open_basedir.

Common situations: CI jobs that cache a test-ID file between steps and the cache misses or is cleaned; files generated in one container but not mounted into the test container; permission mismatches when the generator and the runner use different users.

Related errors


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