Skip to content
Latchkey

PHP Deprecated (8.x) Failing CI - Deprecations Promoted to Errors

PHP 8.x added many deprecations (nullable implicit, dynamic properties, passing null to non-nullable internals). When error_reporting includes E_DEPRECATED and an error handler escalates notices, or a test runner fails on deprecations, these warnings become hard CI failures.

What this error means

CI fails with "PHP Deprecated: ... in ..." lines, often "Creation of dynamic property" or "Passing null to parameter of internal function is deprecated", even though the app runs. A custom error handler or the test runner converts the deprecation into a failure.

php
PHP Deprecated:  Creation of dynamic property App\Dto::\$extra is deprecated in
/app/src/Dto.php on line 22
# error handler converts E_DEPRECATED to an exception -> CI step exits non-zero

Common causes

New 8.x deprecations now trigger

Dynamic properties, implicit nullable params, and passing null to internal functions became deprecated in PHP 8.x. Upgrading the runner PHP surfaces them all at once.

An error handler escalates E_DEPRECATED

A set_error_handler that throws on any reported level, or a test runner configured to fail on deprecations, turns each deprecation into a fatal failure.

How to fix it

Fix the deprecation at its source

Declare properties (or use #[AllowDynamicProperties]), make nullable params explicit, and stop passing null to internals.

php
class Dto
{
    public ?string \$extra = null; // declare instead of dynamic
}

Scope error_reporting deliberately for the run

If you must defer fixes, exclude E_DEPRECATED rather than silencing all errors - and track the debt.

php
php -d error_reporting='E_ALL & ~E_DEPRECATED' vendor/bin/phpunit

Audit every deprecation before upgrading PHP

  1. Run the suite on the new PHP with deprecations visible but non-fatal first.
  2. Collect the full list, then fix dynamic properties and null-to-internal calls.
  3. Re-enable strict deprecation failure once the list is clear.

How to prevent it

  • Fix deprecations as they appear instead of masking E_DEPRECATED long-term.
  • Declare all properties; use #[AllowDynamicProperties] only as a deliberate bridge.
  • Run the suite against the next PHP version in a matrix to catch deprecations early.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →