sebastianbergmann/phpunit · error · InvalidPhptFileException

PHPT file must not contain text before its first section (li

Error message

PHPT file must not contain text before its first section (line %d)

What it means

parse() iterates lines before the first recognized --SECTION-- header while $section is still the empty string; any line there — a PHP open tag, a UTF-8 BOM, a shebang, a comment, or even a blank line — causes InvalidPhptFileException('PHPT file must not contain text before its first section (line N)'). A valid .phpt file must start directly with a section header, conventionally --TEST--.

Source

Thrown at src/Runner/Phpt/Parser.php:143

                if (!in_array($section, self::SUPPORTED_SECTIONS, true) &&
                    !in_array($section, self::UNSUPPORTED_SECTIONS, true) &&
                    !in_array($section, self::IGNORED_SECTIONS, true)) {
                    throw new UnknownPhptSectionException($section);
                }

                if (isset($sections[$section])) {
                    throw new DuplicatePhptSectionException($section);
                }

                $sections[$section]             = '';
                $sections[$section . '_offset'] = (string) $lineNr;

                continue;
            }

            if ($section === '') {
                throw new InvalidPhptFileException(
                    sprintf(
                        'PHPT file must not contain text before its first section (line %d)',
                        $lineNr,
                    ),
                );
            }

            assert(isset($sections[$section]));

            $sections[$section] .= $line;
        }

        $codeSection = $this->ensureExactlyOneSectionOf($sections, self::FILE_SECTIONS);

        $this->ensureExactlyOneSectionOf($sections, self::EXPECTATION_SECTIONS);

        if (isset($sections['FILEEOF'])) {
            $sections['FILE'] = rtrim($sections['FILEEOF'], "\r\n");

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Make --TEST-- (or another valid section header) the very first line of the file.
  2. Remove leading BOM, shebang, '<?php', comments and blank lines — note that blank lines before the first header are rejected too.
  3. Re-save the file as UTF-8 without BOM.

Example fix

-- before
<?php // example.phpt
--TEST--
Demo

-- after
--TEST--
Demo
Defensive patterns

Strategy: validation

Validate before calling

function assertPhptStartsWithSection(string $phptFile): void
{
    $lines = file($phptFile);

    if ($lines === false || preg_match('/^--[_A-Z]+--/', $lines[0] ?? '') !== 1) {
        throw new RuntimeException($phptFile . ' must start with a section header such as --TEST--');
    }
}

Try / catch

try {
    $sections = (new \PHPUnit\Runner\Phpt\Parser())->parse($phptFile);
} catch (\PHPUnit\Runner\Phpt\InvalidPhptFileException $e) {
    if (str_contains($e->getMessage(), 'text before its first section')) {
        // strip leading BOM/blank lines/comments so the file starts with --TEST--
    }
}

Prevention

When it happens

Trigger: A .phpt file whose first line is '<?php', '#!/usr/bin/env php', a license comment, leading whitespace/blank lines, or a UTF-8 BOM saved by the editor; anything before the first /^--([_A-Z]+)--/ line is rejected, and the message reports the offending line number.

Common situations: Generating .phpt files from templates that prepend a header; editors saving with BOM; converting old tests that had a leading comment; concatenating files while building a test suite.

Related errors


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