sebastianbergmann/phpunit · error · FileDoesNotHaveLineException

File "%s" does not have line %d

Error message

File "%s" does not have line %d

What it means

To hash a baseline issue, PHPUnit reads the file and takes the sha1 of line N (FILE_IGNORE_NEW_LINES, zero-based index line-1). The file exists but has fewer lines than requested, so FileDoesNotHaveLineException reports the file and line. Like error 111, this only happens when the hash is computed — Issue::from() with null hash, i.e. during --generate-baseline or when the ErrorHandler re-hashes a freshly triggered issue to compare it against a loaded baseline.

Source

Thrown at src/Runner/Baseline/Issue.php:138

     * @param positive-int     $line
     *
     * @throws FileDoesNotExistException
     * @throws FileDoesNotHaveLineException
     *
     * @return non-empty-string
     */
    private static function calculateHash(string $file, int $line): string
    {
        $lines = @file($file, FILE_IGNORE_NEW_LINES);

        if ($lines === false && !is_file($file)) {
            throw new FileDoesNotExistException($file);
        }

        $key = $line - 1;

        if (!isset($lines[$key])) {
            throw new FileDoesNotHaveLineException($file, $line);
        }

        $hash = sha1($lines[$key]);

        assert($hash !== '');

        return $hash;
    }
}

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Regenerate the baseline after source changes: vendor/bin/phpunit --generate-baseline=<path>.
  2. If only some entries are stale, delete the baseline file (or offending entries) and regenerate.
  3. When integrating Issue programmatically, supply the hash explicitly so no line lookup happens.

Example fix

# before: stale baseline after editing sources
vendor/bin/phpunit --baseline=.phpunit/baseline.xml

# after: regenerate, then run
vendor/bin/phpunit --generate-baseline=.phpunit/baseline.xml
vendor/bin/phpunit --baseline=.phpunit/baseline.xml
Defensive patterns

Strategy: validation

Validate before calling

// Before hashing line N of a file
$lines = file($file, FILE_IGNORE_NEW_LINES);
if ($lines === false || count($lines) < $line) {
    // file shrank or line moved: skip or regenerate the baseline
    return;
}

Prevention

When it happens

Trigger: A baseline was generated against an older revision; the file has since been edited (lines removed), and on the next run the recorded line number is beyond EOF when re-hashed. Also: generating a baseline for dynamically generated code whose line numbers exceed the on-disk file.

Common situations: Editing source between --generate-baseline and the next --baseline run; rebases and line shifts; PHAR or generated-code paths with synthetic line numbers.

Related errors


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