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
- Make --TEST-- (or another valid section header) the very first line of the file.
- Remove leading BOM, shebang, '<?php', comments and blank lines — note that blank lines before the first header are rejected too.
- 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
- Save .phpt files as UTF-8 without BOM.
- Never put '<?php', shebangs or license comments at the top of a .phpt file; description text belongs in --TEST-- or --DESCRIPTION--.
- When generating .phpt files from templates, assert the first output line is a section header.
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
- --%s-- is not a valid PHPT section
- --%s-- section occurs more than once
- PHPT file must contain one of the sections --%s--
- PHPT file must not contain more than one of the sections --%
- --%s-- section is empty
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/ae2305f12f7fade7.
Report an issue: GitHub.