sebastianbergmann/phpunit · error · ErrorException
E_USER_ERROR was triggered
Error message
E_USER_ERROR was triggered
What it means
PHPUnit installs its own error handler while a test runs. When code executed inside that test calls trigger_error() with E_USER_ERROR severity, the handler emits a Test\ErrorTriggered event and then throws PHPUnit\Runner\ErrorException('E_USER_ERROR was triggered') so the test is marked as errored. Lower severities (notice, warning, deprecation) are only recorded; E_USER_ERROR is the only user-raised level converted into an exception, because PHP treats it as an abort-level error.
Source
Thrown at src/Runner/ErrorHandler.php:310
$ignoredByBaseline,
$ignoredByTest,
$this->deprecationIgnoredByFilter($errorString, $errorFile, $errorLine, $trigger),
$trigger,
$this->stackTrace($errorFile, $errorLine),
);
break;
case E_USER_ERROR:
Event\Facade::emitter()->testTriggeredError(
$test,
$errorString,
$errorFile,
$errorLine,
$suppressed,
);
throw new ErrorException('E_USER_ERROR was triggered');
/**
* No other error type that can be handled by a user-defined
* error handler is raised by PHP 8.
*/
// @codeCoverageIgnoreStart
default:
return $handledByPreviousErrorHandler;
// @codeCoverageIgnoreEnd
}
return $handledByPreviousErrorHandler;
}
public function handleNonTestCaseIssue(int $errorNumber, string $errorString, string $errorFile, int $errorLine): true
{
/**
* A previously registered error handler may delegate an error that is beingView on GitHub (pinned to f123cdb2a2)
Solutions
- Fix the code under test to throw an exception instead of calling trigger_error(..., E_USER_ERROR).
- If the error is expected in this test, declare it: $this->expectException(\PHPUnit\Runner\ErrorException::class); before the triggering call.
- If the call must not abort the test, wrap it in a try/catch for \PHPUnit\Runner\ErrorException inside the test and assert on state afterwards.
- Downgrade the severity to E_USER_WARNING or E_USER_DEPRECATED when abort semantics are not required; PHPUnit then records the issue instead of throwing.
Example fix
// before
public function testLegacyAbort(): void
{
LegacyLogger::fail('disk full'); // calls trigger_error(..., E_USER_ERROR)
self::assertTrue(true);
}
// after
public function testLegacyAbort(): void
{
$this->expectException(\PHPUnit\Runner\ErrorException::class);
LegacyLogger::fail('disk full');
} Defensive patterns
Strategy: try-catch
Try / catch
// inside a PHPUnit test
try {
LegacyCode::run(); // may call trigger_error(..., E_USER_ERROR)
self::assertTrue($expectedState);
} catch (\PHPUnit\Runner\ErrorException $e) {
// reached only when E_USER_ERROR was raised during the call
self::assertSame('E_USER_ERROR was triggered', $e->getMessage());
} Prevention
- Prefer exceptions over trigger_error(E_USER_ERROR) in code you own; PHPUnit converts that severity into an exception.
- Pair any test of intentional E_USER_ERROR aborts with expectException(\PHPUnit\Runner\ErrorException::class).
- Grep for 'trigger_error(' in dependencies before writing tests around legacy components to know what to expect.
When it happens
Trigger: Test code, or production code the test invokes, executes trigger_error($message, E_USER_ERROR) (E_USER_ERROR is also the default severity of trigger_error(), so a bare trigger_error('msg') in PHP 8 hits this path). Typical sources: legacy libraries that signal fatal conditions via user errors instead of exceptions, or old hand-rolled assertion/abort helpers.
Common situations: Writing tests around legacy PHP code that used trigger_error(E_USER_ERROR) instead of throwing; a dependency raising E_USER_ERROR deep inside a code path under test; porting old test suites whose helpers abort via user errors.
Related errors
- Subscriber "%s" does not implement any known interface - did
- Unknown event type "%s"
- Subscriber "%s" does not implement a known interface
- Subscriber "%s" does not exist or is not an interface
- Event class "%s" does not exist
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/c6764a2f2a8c4816.
Report an issue: GitHub.