Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

This is the PHP error messages database: a reference collecting every error, warning, notice, and deprecation message that the PHP engine can emit, each with a plain-language explanation of what it means and why PHP raised it. PHP’s own output is often terse — a single line pointing at a line number, with no context on the underlying rule being broken. This book exists to close that gap, one message at a time.

The database is maintained by Exakat, the static analysis engine for PHP, and draws on the same body of knowledge Exakat uses to detect issues in real codebases before they reach production. Where relevant, each entry links back to the PHP language construct involved, notes which PHP version introduced or changed the behavior, and points to further reading in the official manual or RFCs.

You can reach any message in two ways. If you already have the exact error text — copied straight from a stack trace or log file — search for it directly; messages are indexed verbatim, including printf-style placeholders such as %s and %d. If you’re exploring more broadly, browse by syntax error, by tag (deprecation, type error, visibility, and so on), or by feature to see every message associated with a given PHP language construct.

This book tracks PHP’s evolution release by release: deprecation notices that will become fatal errors in future versions are flagged as such, so you can fix them ahead of an upgrade rather than after one breaks production.

Contributions

Contributions are welcomed, by submitting PR to the repository

  • New or missing error messages to be added, preferably with their reproduction code
  • Extra links to external resources
  • Documentation complements
  • Checks on the related notions and thesaurus

Syntax Errors

Syntax errors

Here is a list of classic syntax errors, met in every day code. Some common solutions are listed with them, so as to help anyone meeting them.

Tags

Tag index

Features

Features index

Index

“static::” is not allowed in compile-time constants

Description

The static keyword is a relative class identifier. It is resolved at execution time, depending on which class is calling the expression.

In the case of constants, such as class constants or default values in parameters or properties, they must be known at compile time, to be usable as soon as the application start.

On the other hand, self and parent are valid relative values, as there can only be one.

Example

<?php

interface I {
    const C = static::NAME;
}

class X {
	public $c = static::name;
    function foo($c = static::NAME) {}
}

?>

Alternatives

  • Use self::.
  • Set the value dynamically, at execution time.

$GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax

Description

Since PHP 8.1, it is not possible to replace $GLOBALS entirely. It has to be modified at the index level, and not as a whole.

The error message is a bit misleading: on the spot operations with index are still possible, such as ++ or array_map or array_walk.

This means that $GLOBALS['index'] may be written, while $GLOBALS cannot.

$GLOBALS['index'] and $GLOBALS can still be used for reading.

Example

<?php

$GLOBALS = [];

// That is also OK
$x = 3;
echo $GLOBALS['x']++;

?>

Alternatives

  • Make a loop over $GLOBALS and update each index individually.
  • Avoid updating $GLOBALS: keep a copy in another variable.

%d arguments are required, %d given

Description

The actual number of arguments of the function is commanded by the first argument: there must be an extra argument for every %s in that argument. In the illustration code, there are 4 expected arguments, on top of the first one, and only 2 arguments, including the first one.

This error message is related to the PHP native functions printf(), vprintf(), sprintf(), fprintf(), vfprintf().

Example

<?php

// count() has one or two arguments
count($array, $recursive, $tooMany);

// printf()'s number of arguments depends on the first one
printf('%s %s %s %s', $variable);

?>

Literal Examples

  • 4 arguments are required, 2 given

Alternatives

  • Reduce the number of %s in the first argument.
  • Add the missing argument in the function call.
  • Replace the %s by %%s.

In previous PHP versions, this error message used to be :ref:too-few-arguments.

%s“ returned as member variable from __sleep() but does not exist

Description

The magic method __sleep must return a list of properties of the current class. Any private property defined in the parent are excluded.

The returned array should be an array of strings, with the name of each property, without the initial $ sign.

Example

<?php

class X {
    public $p = 1;
    function __sleep() {
        return ['p', 'q', []];
    }
}

serialize(new X);

?>

Literal Examples

  • “q” returned as member variable from __sleep() but does not exist
  • “Array” returned as member variable from __sleep() but does not exist

Alternatives

  • Remove all unknown properties.
  • Check the format of the property name, and remove the $ sign.
  • Check the visibility of the properties: private properties from parents are excluded.

“%s” will be interpreted as a class name. Did you mean “%s”? Write “%s”%s to suppress this warning

Description

PHP offers several native type, such as bool or int. These names may also be confused with boolean and integer, which are not PHP native types. They are valid for custom code usage, including creating classes or interfaces. To avoid such confusion, PHP emits this error message to make sure that integer is confused with int.

boolean, for bool, integer, for int, double, for float, and resource, for \resource, are all subjects to this error.

Example

<?php

function foo() : boolean {} 

?>

Literal Examples

  • “boolean” will be interpreted as a class name. Did you mean “bool”? Write “\boolean” to suppress this warning
  • “resource” will be interpreted as a class name. Did you mean “\resource”?

Alternatives

  • Use the PHP native type.
  • Create a use statement for the actual type.
  • Add the initial \ with this name.

%s%s%s() does not accept unknown named parameters

Description

printf() and sprintf() take a format string as first argument, and an arbitrary number of arguments after that. Those extra arguments are only positional. Hence, it is not possible to use ellipsis on an array with string keys.

This error also applies to array functions that handles the parameters as a list: in a list, the names are not important.

Example

<?php

printf('%s', ...['a' => 2]);

array_merge([1, 2], a: [3, 4]);

array_intersect([1, 2], a: [3, 4]);

array_diff_key([1, 2], [3, 4], a: [5, 6]);

?>

Literal Examples

  • printf() does not accept unknown named parameters
  • array_merge() does not accept unknown named parameters
  • array_diff_key() does not accept unknown named parameters
  • array_intersect() does not accept unknown named parameters

Alternatives

  • Use array_values() on the array, before the ellipsis.

%s%s%s(): Argument #%d%s%s%s must be passed by reference, value given

Description

When a parameter is set to be passed by reference, there is a & character before its name. In that case, the argument must be a data container, such as a variable, a property, a static property, an array index, but it cannot be a literal value, a constant, or the result of an expression.

Example

<?php

function foo(&$a) {}

// invalid cases
foo(1);
foo(1 + 2);

const A = 1;
foo(A);

class X {
    const B = 2;
}
foo(X::B);

?>

Literal Examples

  • foo(): Argument #1 ($a) must be passed by reference, value given

Alternatives

  • Store the value in a variable and passe the variable.
  • Remove the reference in the method signature.

In previous PHP versions, this error message used to be :ref:parameter-%d-must-be-passed-by-reference.

%s%s%s(): Return value must be of type %s, %s returned

Description

This error appears when calling a method with a return value, but without an explicit return statement. This means that when the method reachs its end, eventually, it will end without a returned value. Yet, the method signature declares that it will return a specific type.

The error is also emitted for property hooks, in particular the get one: its return type is the same as the type of the property.

A different error message is returned when an empty return statement is used.

Example

<?php

function foo() : int {}

class X {
    public int $p {
        // The type of the property is the return type of the hook
        get => [$this->p];
    }
}

?>

Literal Examples

  • foo(): Return value must be of type int, none returned

Alternatives

  • Add a return call, with a valid value.
  • Remove the return type.
  • Add a null to the return type, and return it (void is not possible with another type).

%s() expects exactly 0 arguments, %d given

Description

The mentioned method does not accept any argument, and reports it.

This is the case of func_num_args(), get_called_class(), error_get_last(), json_last_error_msg(), mysqli_connect_errno(), mysqli_get_links_stats(), mysqli_connect_error(), DOMDocumentFragment::__construct(), XSLTProcessor::hasExsltSupport(), etc. It is also the case for the property hook get().

Example

<?php

function dump_error(callable $callable) {
    try {
        var_dump($callable());
    } catch (Throwable $e) {
        var_dump($e->getMessage());
    }
}

?>

Alternatives

  • Remove all arguments when calling such method.

%s() has been disabled for security reasons

Description

The function mentioned in the message was disabled with the disable_functions directive. It is not possible to use it, nor to redefine it.

Example

<?php

shell_exec('ls -la');

?>

Literal Examples

  • shell_exec() has been disabled for security reasons

Alternatives

  • Remove the function from the disable_functions directive.
  • Find another function with a similar feature.

In more recent PHP versions, this error message is now :ref:call-to-undefined-function-%s().

%s(): Argument #%d%s%s%s cannot be passed by reference

Description

Passing a literal value, a constant or $GLOBALS where a reference is requested leads to this error.

For literal and constants, global or class, this is due to the value that can’t be modified. It must be put in a variable first.

For $GLOBALS, it is to prevent modifications of its values. It makes the error message a bit surprising. This doesn’t apply to other PHP variables.

A reference argument expected a variable, a property, static or not, or an array element. Usually, a variable is the best choice.

Example

<?php

function foo(&$arg) {}

// passing a literal
foo([]);
// passing $GLOBALS
foo($GLOBALS);

// trying to trim spaces on all GLOBALS
array_walk( $GLOBALS, trim(...));

?>

Literal Examples

  • array_walk(): Argument #1 $GLOBALS cannot be passed by reference

Alternatives

  • Copy $GLOBALS to a variable and pass this variable.
  • Copy the constant value to a variable and pass this variable.
  • Copy the literal value to a variable and pass this variable.

In previous PHP versions, this error message used to be :ref:cannot-pass-parameter-%d-by-reference.

%s(): Argument #%d%s%s%s could not be passed by reference

Description

Methods arguments may be passed by value or by reference. The first one is the default behavior, and the second one is optional: it is identified with the &, before the name of the argument.

When an argument is passed by reference, the calling context passes a variable, and conserves a handle to the modified variable after the execution of the method. The handle points to a data container, such as a variable, a property, a static property or a array item.

When passing literal values or constants, global or class, this error is emitted, as there cannot be a reference to them. They can only be passed by value.

This error message is emitted when a value is returned, and feed into a reference argument.

Example

<?php

function foo(int &$int) {
    // doSomething
}

foo(-3);

?>

Literal Examples

  • foo(): Argument #3 ($int) could not be passed by reference

Alternatives

  • Store the value in a variable, and pass the variable to the method.
  • Remove the reference from the called method signature.

In previous PHP versions, this error message used to be :ref:%s():-argument-#%d%s%s%s-cannot-be-passed-by-reference.

Implicitly marking parameter $%s as nullable is deprecated, the explicit nullable type must be used instead

Description

Until PHP 8.4, it is possible to use a default value of null, on a parameter that is not nullable. This special situation makes the parameter nullable: it may be omitted, or explicitly passed as null. This is a hidden type, as the null type is not explicit, yet it is fully usable.

In PHP 8.4, this is not possible anymore. For consistency reasons, the type must be explicitly displayed. Until then, it was silent.

Example

<?php

function foo(string $s = null) {}

class X {
    function foo(string $s = null) {}
}

?>

Literal Examples

  • foo(): Implicitly marking parameter $s as nullable is deprecated, the explicit nullable type must be used instead
  • X::bar(): Implicitly marking parameter $s as nullable is deprecated, the explicit nullable type must be used instead

Alternatives

  • Add ? to the type.
  • Add null| to the type.
  • Use a default value in the range of the specified type.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See implicitNullable

%s(): Implicitly marking parameter $%s as nullable is deprecated, the explicit nullable type

Description

Before union types existed, PHP let a scalar or class-typed parameter become nullable simply by giving it a default value of null, e.g. function foo(int $x = null). The type itself still reads as int, but the engine silently widened it to also accept null, which is easy to miss when skimming a signature.

As of PHP 8.4, relying on this implicit widening emits a deprecation notice; the parameter still behaves as nullable for now, but the behaviour is expected to be dropped in a future version, at which point only an explicit nullable type would accept null.

Example

<?php

// $x has no type-level '?', but a default of null makes it
// implicitly nullable -- this is the deprecated PHP 5 style.
function foo(int $x = null) {
    var_dump($x);
}

foo(1);

?>

Literal Examples

  • foo(): Implicitly marking parameter $x as nullable is deprecated, the explicit nullable type must be used instead

Alternatives

  • Write the nullable type explicitly with a leading question mark: function foo(?int $x = null).
  • Or use an explicit union type: function foo(int|null $x = null).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s(): never-returning %s must not implicitly return

Description

An implicit return is a method reaching the end of its body block, and ending its execution without an explicit return statement. In fact, PHP executes an implicit return statement, et returns the value NULL. In the case of a method, whose return type is never, this should not happen. There must be a call to die, exit, or throw, or any other mean to prevent this function to reach its normal ending.

This error is only reported at execution time.

Example

<?php

function myDeath(): never {

    if (rand(0, 1)) {
        die();
    }
}

myDeath();

?>

Literal Examples

  • myDeath(): never-returning function must not implicitly return

Alternatives

  • Add a die or exit before the end of the method.
  • Add a throw before the end of the method.
  • Add an infinite loop in the method.

In previous PHP versions, this error message used to be :ref:%s():-never-returning-function-must-not-implicitly-return.

%s(): never-returning function must not implicitly return

Description

A function with the never return type must return anything. This means no return keyword, but also, no possibility to reach the end of the method, as it would trigger automatically a return null;.

Example

<?php

function foo(): never {
    if (true) {
        throw new Exception('bad');
    }
}

foo();
?>

Literal Examples

  • foo(): never-returning function must not implicitly return

Alternatives

  • Add a die at the end of the method.
  • Add a throw at the end of the method.

In more recent PHP versions, this error message is now :ref:%s():-never-returning-%s-must-not-implicitly-return.

%s(): Optional parameter $%s declared before required parameter $%s

Description

A parameter with a default value is only truly optional when every parameter that follows it also has one. PHP has always allowed writing an optional parameter before a required one, but silently converted the earlier one into a required parameter as soon as it was actually called – its default value was never reachable. This has been deprecated since PHP 8.0, and, since PHP 8.1, is no longer just a notice: such a parameter is always treated as required – even when called with named arguments – so omitting it raises an ArgumentCountError instead of falling back to the default.

This particular wording, naming the function, is the current one: PHP 8.4 reworded a batch of parameter- and return-value-related deprecations to prefix the message with FunctionName(): , matching the style already used for most other deprecations.

Example

<?php

// $a looks optional (it has a default), but $b after it has none,
// so $a can no longer really be left out.
function foo($a = 1, $b) {
    return $a + $b;
}

var_dump(foo(2, 3));

?>

Literal Examples

  • foo(): Optional parameter $a declared before required parameter $b is implicitly treated as a required parameter

Alternatives

  • Give the earlier parameter’s default to every parameter that needs one, and move genuinely required parameters first.
  • If the default is only there for backward compatibility, make the parameter nullable (?Type $a = null) and document that null is not a meaningful value on its own.
  • Use named arguments at the call site instead of relying on positional defaults.

In previous PHP versions, this error message used to be :ref:optional-parameter-$%s-declared-before-required-parameter-$%s-is-implicitly-treated-as-a-required-parameter.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.4, the same deprecation was worded “Optional parameter $a declared before required parameter $b is implicitly treated as a required parameter”, without the leading “FunctionName(): “ prefix. Before PHP 8.1, PHP 8.0 used a different wording still: “Required parameter $b follows optional parameter $a”.](Prior to PHP 8.4, the same deprecation was worded “Optional parameter $a declared before required parameter $b is implicitly treated as a required parameter”, without the leading “FunctionName(): “ prefix. Before PHP 8.1, PHP 8.0 used a different wording still: “Required parameter $b follows optional parameter $a”.)

%s(): Passing null to parameter #%d (%s) of type string is deprecated

Description

PHP has been enforcing non-null parameters to PHP native functions. This started in PHP 8.1. Until then, it was possible to use NULL everywhere, and it would have been cast to an empty string or 0. Nowadays, it is a deprecation.

This applies to all PHP native functions, such as, and not limited to: strtolower(), strip_tags(), trim(), addslashes(), strlen(), rtrim(), etc.

Example

<?php

strlen(null);

?>

Literal Examples

  • strlen(): Passing null to parameter #1 ($string) of type string is deprecated
  • dir(): Passing null to parameter #1 ($path) of type string is deprecated

Alternatives

  • Check the value before calling the function.
  • Use ?? to convert the null into a suitable default value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See dirWithNull

%s(): Return value of the authorizer callback must be of type int, %s returned

Description

Pdo\Sqlite::setAuthorizer() installs a userland callback that SQLite consults before executing most operations, such as creating a table, reading a column, or attaching a database. The callback receives the action being authorized plus up to four contextual strings, and it must return one of the integer constants Pdo\Sqlite::OK, Pdo\Sqlite::DENY or Pdo\Sqlite::IGNORE.

As of PHP 8.5, PDO strictly checks the type of the returned value. If the callback returns anything that is not an int – a string, a boolean, null, or simply nothing because a return statement was forgotten on some branch – a TypeError is thrown instead of the value being silently coerced.

The equivalent method on the standalone SQLite3 extension, SQLite3::setAuthorizer(), enforces the same strict check.

Example

<?php

$pdo = new Pdo\Sqlite('sqlite::memory:');

$pdo->setAuthorizer(function (int $action, ?string $arg1, ?string $arg2, ?string $arg3, ?string $arg4) {
    // Forgot to return an int constant -- this should return Pdo\Sqlite::OK, ::DENY or ::IGNORE
    return $action === Pdo\Sqlite::CREATE_TABLE ? 'allow' : 'deny';
});

$pdo->exec('CREATE TABLE test (id INTEGER)');

?>

Literal Examples

  • Pdo\Sqlite::setAuthorizer(): Return value of the authorizer callback must be of type int, string returned

Alternatives

  • Always return one of the constants Pdo\Sqlite::OK, Pdo\Sqlite::DENY or Pdo\Sqlite::IGNORE from the callback.
  • Add an explicit return statement on every branch of the callback, including the default one.
  • Declare an int return type on the callback so mismatches are caught as soon as they are written.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s(): Return value of the collation callback must be of type int, %s returned

Description

Pdo\Sqlite::createCollation() registers a userland function to be used as an SQL collating sequence. Like strcmp(), the callback receives two strings and must return a negative, zero, or positive int depending on whether the first string sorts before, the same as, or after the second one.

As of PHP 8.5, the return value of the callback is strictly checked. Returning anything that is not an int – for instance a bool from a <=> comparison used incorrectly, or nothing at all because of a missing return – raises a TypeError, instead of the previous behavior where a non-int value silently made the collation undefined.

The legacy PDO::sqliteCreateCollation() method, kept for backward compatibility, is affected by the same strict check.

Example

<?php

$pdo = new Pdo\Sqlite('sqlite::memory:');

$pdo->createCollation('natcmp', function (string $a, string $b) {
    // strcmp() convention expected -- negative, zero or positive int
    return $a <=> $b ? strnatcasecmp($a, $b) <=> 0 : 0;
});

$pdo->exec('CREATE TABLE test (name TEXT)');
$pdo->query('SELECT name FROM test ORDER BY name COLLATE natcmp');

?>

Literal Examples

  • Pdo\Sqlite::createCollation(): Return value of the collation callback must be of type int, bool returned

Alternatives

  • Make sure the callback always returns an int, following the strcmp() convention of negative/zero/positive.
  • Use the spaceship operator <=> directly on the two strings, or on a derived comparable value, since it already returns an int.
  • Declare an int return type on the callback to catch a wrong return value while writing it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s(): Returning by reference from a void function is deprecated

Description

The void type means that the function is not returning anything. So, it doesn’t matter if that nothing is returned by value or by reference.

If the returned value is, nonetheless, collected, it will be null in any case.

Example

<?php

    function &foo(): void { }

?>

Literal Examples

  • foo(): Returning by reference from a void function is deprecated

Alternatives

  • Remove the reference of the function.
  • Remove the type void, and return an actual value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See return_reference_on_void.php

%s" is not a supported builtin type and will be interpreted as a class name. Write "\%s"%s to suppress this warning

Description

resource looks like it should be a builtin type, since it is one of the values returned by gettype(), but it was never turned into an actual type declaration: there is no way to name a specific kind of resource (file handle, curl handle…) in a type.

Since resource is not a reserved word, PHP does not reject it: it silently treats it as the name of a class or interface called resource, which almost never exists, and any call with an actual resource argument then fails with a TypeError.

To help catch the mistake, the compiler emits this warning as soon as it sees the bare word resource in a type position and no class or interface with that name has been imported: it assumes a builtin type was intended. The comparison is case-sensitive, so a capitalized Resource – more plausible as a genuine class name – does not trigger it.

Example

<?php

function readFile(resource $handle): void {
    fclose($handle);
}

?>

Literal Examples

  • “resource” is not a supported builtin type and will be interpreted as a class name. Write “\resource” to suppress this warning

Alternatives

  • Remove the type declaration, or replace it with mixed, since resources cannot be typed more precisely.
  • Prefix the name with a backslash, as in \resource, to tell PHP that a class actually called resource is meant, which suppresses the warning.
  • If a class or interface named resource exists in the current namespace, import it with a use statement so PHP recognizes it, which also suppresses the warning.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s" is returned from __sleep() multiple times

Description

This error is emitted when one of the properties that has to be put to sleep is repeated in the returned array of __sleep(). All the duplicated properties are reported in one pass, although each of them only once. The warning is only triggered when the code is run.

Example

<?php

class X {
    private $data;

    public function __sleep() {
        return ['data', 'data', 'data'];
    }
}

// Create an instance and serialize it
$example = new Example('test');
$serialized = serialize($example);

?>

Literal Examples

  • data“ is returned from __sleep() multiple time

Alternatives

  • Make sure the properties names are all unique in the returned array.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s" will be interpreted as a class name. Did you mean "%s"? Write "\%s"%s to suppress this warning

Description

boolean, integer and double are the names PHP itself uses internally, and returns from gettype(), for the bool, int and float types. They look like legitimate type names, but they were never made valid type declarations; only the short forms are.

Because none of these three words is reserved, PHP does not reject them in a type position: it treats the declaration as the name of a class or interface instead, one that essentially never exists, so any call passes a value of the intended scalar type and still fails with a TypeError.

To catch this common mistake, the compiler recognizes exactly these three words – and only these three, compared case-sensitively, so Boolean or INTEGER are assumed to be genuine class names and do not trigger it – and emits this warning, naming the short form that was probably intended. It only fires when no class or interface with that exact name has been imported in the current file.

Example

<?php

function toggle(boolean $flag): integer {
    return $flag ? 1 : 0;
}

?>

Literal Examples

  • “boolean” will be interpreted as a class name. Did you mean “bool”? Write “\boolean” to suppress this warning
  • “integer” will be interpreted as a class name. Did you mean “int”? Write “\integer” to suppress this warning
  • “double” will be interpreted as a class name. Did you mean “float”? Write “\double” to suppress this warning

Alternatives

  • Replace the alias with the actual scalar type: bool instead of boolean, int instead of integer, float instead of double.
  • Prefix the name with a backslash, as in \boolean, to tell PHP that a class actually called boolean is meant, which suppresses the warning.
  • If a class or interface with that exact name exists in the current namespace, import it with a use statement so PHP recognizes it, which also suppresses the warning.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s %s cannot implement interface %s, extend Exception or Error instead

Description

Throwable is a PHP native and reserved interface. It may be used for typing, such as with catch or parameter typing, but cannot be used directly.

As the message suggest, the best is to extends an existing class that already implements Throwable, such as Error, Exception or any of their children classes.

Several interfaces are reserved by PHP: UnitEnum, BackedEnum, Throwable.

Example

<?php

class X implements Throwable {}

?>

Literal Examples

  • Class X cannot implement interface Throwable, extend Exception or Error instead

Alternatives

  • Extends Exception class.
  • Extends Error class.
  • Extends any of the Exception or Error classes.

%s %s cannot implement previously implemented interface %s

Description

This error reports that an interface has already been implemented by a parent, and, as such, should not be implemented again.

For enumerations, it applies to BackEnum and UnitEnum, as enumerations don’t have parents.

For interfaces and classes, it applies to repetitions of interfaces in the implements list.

It doesn’t apply to duplicate implements between a parent and a child class or interface.

It doesn’t apply to trait, that have no relationship with interfaces.

Example

<?php

enum X implements UnitEnum {}

interface J extends I, I {}

class X implements I {}

// This is OK
// It is also duplicate and useless, but valid.
class Y extends X implements I {}

?>

Literal Examples

  • Enum x cannot implement previously implemented interface UnitEnum

Alternatives

  • Remove duplicate interfaces from the implements keyword on classes.
  • Remove duplicate interfaces from the extends keyword on interfaces.
  • Remove BackEnum and UnitEnum from the implements keyword on an enumeration.

%s %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining method%s (

Description

A class (or a trait, once it is used in a class) that does not provide a body for one or more of its abstract methods – inherited from a parent class, or required by an implemented interface – must itself be declared abstract. Otherwise PHP has no concrete implementation to call when the method is invoked, and it stops with a fatal error while linking the class.

The message lists every abstract method that is still missing a concrete implementation, up to three of them; when there are more, the list ends with ....

This is the templated, general-purpose version of the message: the first %s is replaced by the kind of structure (Class or Interface), the second by its name.

Since PHP 8.5, enums and anonymous classes no longer use this message: they get the dedicated %s %s must implement %d abstract method%s (...) message instead, since neither of them can be declared abstract.

Example

<?php

interface Colorful {
    function color();
}

class Suit implements Colorful {
}

?>

Literal Examples

  • Class Suit contains 1 abstract method and must therefore be declared abstract or implement the remaining method (Colorful::color)

Alternatives

  • Implement the missing method(s), with a body, in the class.
  • Declare the class abstract.
  • Remove the implements/extends clause that brings in the abstract method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See abstractMethodMessageSplit85

%s %s inherits both %s::%s and %s::%s

Description

PHP reports duplicate constant definitions in different interfaces.

This is very unusual occurrence, reported at linting time. It may also lead to quite a set back when one has to untangle these definitions.

So, shall we always give unique names across interfaces? Or just avoid multiple interfaces with constants on the same class?

There is no ‘use’ expression to solve the conflict. The same applies to traits, though they can resolve conflicts with the use expression.

Also, multiple same methods in different interface are OK.

Example

<?php

interface Test1 {
    const FOO = 10;
}

interface Test2 {
    const FOO = 10;
}

class Test implements Test1, Test2 {
}

echo Done\n;
?>

Literal Examples

  • class test inherits both test1::FOO and test2::FOO

Alternatives

  • Remove one of the constant definition.
  • Rename one of the interface constant.
  • Define the conflicted constant in the class.
  • Remove one of the interfaces.

%s %s must implement %d abstract method%s (

Description

An enum, or an anonymous class, that does not provide a body for one or more of its abstract methods – inherited via an implemented interface – must implement all of them, since, unlike an ordinary class, neither an enum nor an anonymous class can be declared abstract to defer the implementation.

The message lists every abstract method that is still missing a concrete implementation, up to three of them; when there are more, the list ends with ....

This is the templated, general-purpose version of the message: the first %s is replaced by the kind of structure (Enum or Class, the latter for anonymous classes), the second by its name.

Before PHP 8.5, anonymous classes used the generic %s %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining method%s (...) message instead of this one, since only enums had this dedicated message. Also, before PHP 8.5, the wording for enums included the word ‘private’ (must implement %d abstract private method%s), which was corrected.

Example

<?php

interface Colorful {
    function color();
}

enum Suit implements Colorful {
    case Hearts;
}

?>

Literal Examples

  • Enum Suit must implement 1 abstract method (Colorful::color)
  • Class Colorful@anonymous must implement 1 abstract method (Colorful::color)

Alternatives

  • Implement the missing method(s), with a body, in the enum or the anonymous class.
  • Remove the implements clause that brings in the abstract method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See abstractMethodMessageSplit85

%s %s must implement interface %s as part of either %s or %s

Description

It is not possible to implement directly the mentioned interface. That interface is actually implemented by a selection of PHP native classes: these classes may be extended, and, as such, the children classes also implements the initial interface.

This error message is applicable to a few PHP native interfaces, such as Throwable (via Error and Exception) and Traversable (via Iterator and IteratorAggregate).

Example

<?php

enum E implements Traversable {}

class X implements Throwable {}

?>

Literal Examples

  • Enum Foo must implement interface Traversable as part of either Iterator or IteratorAggregate
  • Class X cannot implement interface Throwable, extend Exception or Error instead

Alternatives

  • Extends one of the classes mentioned in the error message.
  • Remove the implementations and its interface.

In previous PHP versions, this error message used to be :ref:class-%s-must-implement-interface-%s-as-part-of-either-%s-or-%s.

%s and %s define the same constant (%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed

Description

There is not conflict resolution, when a class and a trait defined the same constant. Both constants must be identical, or face the above error message.

In order to be compatible, the constants in the class AND in the trait must have the same name, the same value (after eventual resolution of the expression), same visibility and the same type.

In the case that the constant is defined in a parent class as private, the trait may defined it again without conflict.

Example

<?php

class X {
	private const A = 2;
}

trait T { 
	protected const null|int A = 1 + 1;
	public const null|int B = 1;
	public const null|int C = 1 + 2;
}

class Y extends X {
	protected const int B = 2;
	public const ?int C = 3;
	
	use T; 
}
?>

Literal Examples

  • y and t define the same constant (B) in the composition of y. However, the definition differs and is considered incompatible. Class was composed

Alternatives

  • Synchronise the constants to make them compatible.
  • Remove the constant from the class.
  • Remove the constant from the trait.

%s and %s define the same hooked property ($%s) in the composition of %s. Conflict resolution between hooked properties is currently not supported. Class was composed

Description

When a class and a trait it uses both declare hooks for a property of the same name, PHP cannot merge the two definitions, even when the hooks are effectively identical.

For plain properties, a trait property is simply overridden by an identically named property in the using class, as long as the two are type-compatible. For methods, name clashes between traits can be settled with the insteadof and as operators. Hooked properties have neither mechanism: there is no way to tell PHP which of the two conflicting sets of hooks (get/set) should win, so the compiler always raises a fatal error instead of picking one silently.

The same restriction applies when two different traits, both used by the same class, declare hooks for a property with the same name.

Example

<?php

trait T {
    public $prop {
        get { echo __METHOD__, PHP_EOL; }
        set { echo __METHOD__, PHP_EOL; }
    }
}

class C {
    use T;

    public $prop {
        get { echo __METHOD__, PHP_EOL; }
        set { echo __METHOD__, PHP_EOL; }
    }
}

?>

Literal Examples

  • C and T define the same hooked property ($prop) in the composition of C. Conflict resolution between hooked properties is currently not supported. Class was composed

Alternatives

  • Rename the property in the trait or in the class so that they no longer collide.
  • Remove the hooks from the property in the class, and rely solely on the trait’s hooks.
  • Remove the hooks from the property in the trait, and only declare hooks in the class.
  • Move the shared behaviour into a method that both the trait and the class hooks can call, instead of duplicating the hooks.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed

Description

There is no conflict resolution for properties: when two traits used by the same class declare a property with the same name, the property must be defined identically in both, or PHP raises this error while composing the class.

To be considered compatible, the property must have the same visibility, the same type, the same default value, and the same readonly/static modifiers in every trait it comes from.

Unlike methods, property conflicts cannot be settled with an insteadof or as rule in the use block: the only way out is to make the definitions match, or to remove the property from all but one trait.

Example

<?php

trait A {
    public int $count = 0;
}

trait B {
    protected int $count = 1;
}

class C {
    use A, B;
}

?>

Literal Examples

  • A and B define the same property ($count) in the composition of C. However, the definition differs and is considered incompatible. Class was composed

Alternatives

  • Make the property declaration identical (visibility, type, default value and modifiers) in every trait.
  • Remove the property from all traits but one.
  • Declare the property directly on the class instead, and remove it from the traits.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s cannot implement %s - it is not an interface

Description

The implements keyword must use an interface, and cannot use anything else. In particular, it cannot be another class, enumeration or trait. All four structures CITE (class, Interface, Trait and Enumeration) use the same namespaces, and they cannot be told apart by reading the name only.

Indeed, when the structure has no definition, PHP reports interface-"E" not found.

Example

<?php

enum E {}
class X implements E {}

?>

Literal Examples

  • X cannot implement e - it is not an interface

Alternatives

  • Make sure the implements structure is an interface, not a class, trait or enumeration.

%s cannot use %s - it is not a trait

Description

In a class definition, the use expression must only use traits. All other structures, such as class, interface, enum or else, are not allowed.

Example

<?php

class X {}

class Y {
	use x; 
}
?>

Literal Examples

  • y cannot use x - it is not a trait

Alternatives

  • Remove the use expression that uses the class.
  • Fix the name of the class, and use an existing trait.

%s class %s cannot extend %s class %s

Description

This is the generic form of the error emitted when a readonly class and a non-readonly class try to extend one another: the first two %s are Readonly/Non-readonly plus the child class name, the last two are readonly/non-readonly plus the parent class name.

readonly is a class-wide modifier: it applies to every property declared in the class. Because a subclass inherits all of its parent’s properties, mixing a readonly class with a non-readonly one in the same hierarchy would leave some properties ambiguous about whether they can be written to after construction. PHP forbids this by requiring every class in an inheritance chain to share the same readonly status.

Example

<?php

readonly class Foo
{
}

class Bar extends Foo
{
}

?>

Literal Examples

  • Readonly class Bar cannot extend non-readonly class Foo
  • Non-readonly class Bar cannot extend readonly class Foo

Alternatives

  • Make both classes readonly.
  • Make both classes non-readonly.
  • Make both classes non-readonly and apply readonly per property instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s function %s::%s() cannot be declared private

Description

A method may be private, as in only available to current class, or abstract, as in always redefined in a child class, but not both at the same time.

These two properties are mutually exclusive.

Example

<?php

class X {
	private abstract function foo() ;
}

?>

Literal Examples

  • abstract function X::foo() cannot be declared private

Alternatives

  • Make the method protected or public.
  • Remove the abstract keyword.

%s function %s::%s() cannot contain body

Description

A method that is abstract – either explicitly declared abstract, or implicitly abstract because it belongs to an interface – is only a signature: it must not have an implementation.

The first %s in the message is Interface when the method is declared inside an interface, and Abstract when it is an explicitly abstract method of a class or trait.

Example

<?php

interface Colorful {
    function color() {
        return 'red';
    }
}

?>

Literal Examples

  • Interface function Colorful::color() cannot contain body
  • Abstract function C::color() cannot contain body

Alternatives

  • Remove the method body, keeping only the signature followed by a semicolon.
  • Remove the abstract keyword, or move the method out of the interface, if it should have an implementation.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s hook of property %s::$%s must accept exactly one parameters

Description

When the set hook of a property is declared with an explicit parameter list, that list must contain exactly one parameter: the value being assigned. Declaring zero, two, or more parameters is not allowed.

This is different from omitting the parenthesis altogether, in which case the hook implicitly receives the value through a variable named $value.

Example

<?php

class X
{
    public string $property {
        set($a, $b) {
            $this->property = $a;
        }
    }
}

?>

Literal Examples

  • set hook of property X::$property must accept exactly one parameters

Alternatives

  • Keep only one parameter in the hook’s parameter list.
  • Remove the parameter list entirely and use the implicit $value variable instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s implements the Serializable interface

Description

The Serializable interface (serialize()/unserialize()) was PHP’s original hook for customizing object serialization, but it has a well-known flaw: it cannot represent the identity and reference structure of nested objects correctly, which is why __serialize()/__unserialize() were introduced in PHP 7.4 as a full replacement.

As of PHP 8.1, any non-abstract class that implements Serializable without also implementing both __serialize() and __unserialize() emits this deprecation notice as soon as the class is declared (not just when an instance is serialized). A class that implements Serializable and the two magic methods is not affected – that combination remains the recommended way to support both old and new PHP versions.

Example

<?php

class Foo implements Serializable {
    public function serialize(): string {
        return '';
    }

    public function unserialize($data): void {
    }
}

new Foo;

?>

Literal Examples

  • Foo implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary)

Alternatives

  • Replace serialize()/unserialize() with __serialize(): array and __unserialize(array $data): void.
  • If backward compatibility with PHP < 7.4 is required, keep implementing Serializable but also add __serialize() and __unserialize() – only the interface without the magic methods triggers the notice.
  • Drop custom serialization handling entirely if the default property-based serialization is sufficient.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

%s is not supported on type %s

Description

This error is reported when an operation is attempted indirectly on a wrong type of data. Here, there is an attempt to add 3 values, one of which is an array.

Example

<?php

$array = [ 1, 2, [3]];
print array_sum($array);

$array = [ 1, 2, (object) [3]];
print array_product($array);

?>

Literal Examples

  • Addition is not supported on type array
  • Multiplication is not supported on type object

Alternatives

  • Check that the array only contains numbers.

%s method %s::%s() must not be abstract

Description

Interface methods are implicitly abstract: they never carry a body, since an interface only declares a contract. Writing the abstract keyword explicitly on an interface method is therefore redundant, and PHP rejects it.

The same message is used for enums, since 8.5: an enum can never be declared abstract, so none of its own methods can be abstract either (its cases are not classes that could provide the missing implementation).

This is the templated, general-purpose version of the message: the first %s is replaced by the kind of structure (Interface or Enum), the second and third by the class name and the method name.

Before PHP 8.5, declaring an abstract method directly inside an enum body produced the generic %s %s must implement %d abstract method%s (...) message instead of this dedicated one.

Example

<?php

interface Colorful {
    abstract function color();
}

?>

Literal Examples

  • Interface method Colorful::color() must not be abstract
  • Enum method Suit::foo() must not be abstract

Alternatives

  • Remove the abstract keyword from the method declaration.
  • If the method needs a real implementation, give it a body instead of declaring it abstract.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See abstractMethodMessageSplit85

%s virtual property %s::$%s must not specify asymmetric visibility

Description

A virtual property is related to property hooks: it is a property whose hook do not use the underlying property for storage, but uses another one (or, like here, none).

When the set or get visibility doesn’t apply, this error is displayed. The error message may start with Read-only or Write-only.

Example

<?php

class X {
	public private(set) int $p {
		set {}
	}
}

class Y {
	public private(set) int $p {
		get {}
	}
}

?>

Literal Examples

  • Write-only virtual property X::$p must not specify asymmetric visibility
  • Readonly-only virtual property Y::$p must not specify asymmetric visibility

Alternatives

  • Remove the asymmetric visibility from the definition of the property.
  • Remove the property hook from the definition of the property.
  • Remove the virtual property, by making the property hook use the underlying property.

%s::$%s has #[\Override] attribute

Description

PHP 8.5 extends the #[\Override] attribute, previously usable only on methods, so that it can also be applied to properties. It tells the engine that the property is expected to override a property of the same name declared in a parent class or an implemented interface, so that the engine can check that this is really the case.

Here, Y::$b is marked as overriding, but X (the parent of Y) has no $b property at all – only $a. Since there is nothing to override, the attribute is meaningless, and PHP reports it as an error at compile time. The full message continues with ‘, but no matching parent property exists’.

This error is also raised when the class using the attribute has no parent at all, or when the property is declared in a trait whose using class has no matching parent property.

Example

<?php

class X {
    public int $a = 1;
}

class Y extends X {
    #[\Override]
    public int $b = 2;
}

?>

Literal Examples

  • Y::$b has #[\Override] attribute, but no matching parent property exists

Alternatives

  • Remove the #[\Override] attribute.
  • Rename the property to match the name used by the parent class or interface.
  • Add the property, with the same name, to the parent class.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See overrideAttributeOnProperty85

%s::%s() has #[\Override] attribute, but no matching parent method exists

Description

This error message has two sources: it happens, at compilation time, when the class has no parent, yet has a method with Override attribute. Since the attribute implies that the method is overriding a parent’s method, this is not possible.

The second cause is a method that has no counterpart in the parents’ classes: there, the attribute plays its actual role.

This error happens when the Override attribute was used in PHP version 8.2, or older, and then, the code was moved to PHP 8.3. With the last version change, the attribute became active, and the code is now actually checked.

Example

<?php

class X {
	#[Override]
	function foo();
}

class Y extends X {
	#[Override]
	function goo();
}

?>

Alternatives

  • Remove the Override attribute.
  • Add a method with the same name to the parent class.
  • Rename the current method to one that is present in the parent.
  • Stay on PHP 8.2.

%s::%s(): Return type must be %s when declared

Description

The magic methods __sleep and __serialize may be left without a return type. By construction, PHP uses array for them.

So, when a return type is written in the source, for these methods, it must be array.

Here is the list of compulsory return types:

  • __destruct() : void
  • __construct() : void
  • __unserialize() : void
  • __unset() : void
  • __set() : void
  • __serialize() : array
  • __isset() : bool
  • __toString() : string.

Example

<?php

class X {
    function __construct() : int {}

    function __sleep() : int {}
    
    function __serialize() : int {} 

    function __isset() : int {} 
}

?>

Literal Examples

  • X::__sleep(): Return type must be array when declared
  • X::__construct(): Return type must be void when declared
  • X::__isset(): Return type must be bool when declared

Alternatives

  • Give the correct return type to the magic method.
  • Remove the return type of the magic method.

%s::%s cannot override final constant %s::%s

Description

The final keyword prevents any child class to define the same constant or method. The final const may overwrite a parent’s definition, but this is the definitive value associated to the constant. Child class must define a distinct constant name.

Example

<?php

class X {
	final const A = 1;
}

class Y extends X {
	const A = 1;
}

?>

Literal Examples

  • Y::A cannot override final constant X::Y

Alternatives

  • Remove the final option in the parent class.
  • Rename the non-final constant in the child class.

%s::%s has #[\Override] attribute

Description

PHP 8.6 extends the #[\Override] attribute, previously usable only on methods and properties, to class constants and enum cases, the later being internally a special kind of class constant. It tells the engine that the constant is expected to override a constant of the same name declared in a parent class or an implemented interface, so that the engine can check that this is really the case.

Here, Square::COLOR is marked as overriding, but Shape, the interface Square implements, only declares SIDES, not COLOR. Since there is nothing to override, the attribute is meaningless, and PHP reports it as an error at compile time. The full message continues with ‘, but no matching parent constant exists’.

Only public and protected constants of a parent class or implemented interface satisfy the attribute; private constants do not count. This error is also raised when the class using the attribute has no parent and implements no interface at all.

Example

<?php

interface Shape {
    const SIDES = 0;
}

class Square implements Shape {
    #[\Override]
    const SIDES = 4; // Fine, overrides Shape::SIDES

    #[\Override]
    const COLOR = 'blue'; // Fatal error, no matching parent constant
}

?>

Literal Examples

  • Square::COLOR has #[\Override] attribute, but no matching parent constant exists

Alternatives

  • Remove the #[\Override] attribute.
  • Rename the constant, or enum case, to match one declared in a parent class or interface.
  • Add a constant with the same name to the parent class or interface.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See overrideAttributeOnConstant86

%s::__sleep() should return an array only containing the names of instance-variables to serialize

Description

The return type of __sleep is actually array, even when it is not mentioned. Any other returned value generate this error.

Example

<?php

class X {
    function __sleep() {
        return 1;
    }
}

serialize(new X);

?>

Alternatives

  • Return an array from __sleep.
  • Add the return type array and return an array from __sleep.
  • Remove the __sleep() method.

In previous PHP versions, this error message used to be :ref:sleep-should-return-an-array-only-containing-the-names-of-instance-variables-to-serialize..

%s::__toString() must return a string

Description

The magic method __toString converts the current object into a string. Hence, and even if the return type of that method is not explicitly set, it MUST return a string.

With strict types, it may only be a string. Without them, integers and booleans are auto cast silently.

Adding the return type or not does not change this behavior. It is actually set, and could not be any other type anyway.

Example

<?php

class X {
    function __toString() {
        return 1;
    }
}

(string) (new X);

?>

Literal Examples

  • X::__toString() must return a string

Alternatives

  • Return a string.
  • Cast the value to a string before returning.

‘%s’ not in the ‘loop’ or ‘switch’ context

Description

break and continue are used to jump out of a loop, and proceed from the end of that loop. Since PHP 7.0, it is not possible to use them outside such a structure.

They can’t be used in a match.

Example

<?php

continue;

break;

?>

Literal Examples

  • ‘break’ not in the ‘loop’ or ‘switch’ context
  • ‘continue’ not in the ‘loop’ or ‘switch’ context

Alternatives

  • Remove the break.
  • Remove the continue.
  • Move the break inside a switch block.
  • Move the continue inside a loop block: for, foreach, while, do..while.

‘%s’ operator accepts only positive integers

Description

The break and continue operators only accepts a positive integer as explicit operand.

break and continue exit from the current loop. By default, it only exits the current loop; when a higher number is passed, they also exit the next loops.

It makes no sense to exit 0 loops (no need for break then), or a negative number of loop (call a new foreach). Break only works with literal integers, and doesn’t compile otherwise.

Example

<?php

break 1.2;

continue -1;

?>

Literal Examples

  • ‘break’ operator accepts only positive integers
  • ‘continue’ operator accepts only positive integers

Alternatives

  • Round the number to the closest integer.
  • Remove the call to break altogether.
  • Move the loop in a separate method, and use return to break out of the loop.
  • Use a goto to jump out of the loop.

‘%s’ operator with non-integer operand

Description

The break and continue operators only accept a positive non-null literal integer.

Beyond the obvious improper code that is break 1.2, even storing the number of break levels in a constant or a variable is not a valid syntax. It can only accept an integer.

Example

<?php

break 1.2;

const A = 1;
break A;

?>

Literal Examples

  • ‘break’ operator with non-integer operand
  • ‘continue’ operator with non-integer operand

Alternatives

  • Round the number to the closest integer.
  • Remove the call to break altogether.
  • Move the loop in a separate method, and use return to break out of the loop.
  • Use a goto to jump out of the loop.

‘%s’ is an invalid class name

Description

self describes the current class. It is a relative class name, as it has no literal value.

As such, it doesn’t have an absolute path version, such as \self. Hence, the error emitted there.

This error is also emitted for static and parent.

It was possible to circumvent this check until PHP 8.1, with namespace\%s syntax, where namespace represents the current namespace.

Example

<?php

function foo(\self $a) {};

function foo( $a) : \self {};

class X {
    private \self $f;
    private \x $f2;
}

?>

Literal Examples

  • ‘\self’ is an invalid class name
  • ‘\parent’ is an invalid class name
  • ‘\static’ is an invalid class name

Alternatives

  • Remove the initial backslash.
  • Use the literal name of the intended class.

‘goto’ into loop or switch statement is disallowed

Description

It is not possible to put a label inside a loop (for, foreach, while, do…while…) or a switch call. Such statement have to be initialized before execution, and the goto would cut short this crucial step.

On the other hand, it is possible to jump from a loop or a switch to outside that structure: then, it terminates it.

It is also possible to use a goto within a loop and a switch.

This is a compilation error: it is detected before execution.

Example

<?php

function foo() {
	goto A;
	
	foreach($a as $b) {
		A:
	}
}

function bar() {
	goto A;
	
	switch($a) {
		case 1:
			A:
			
			break;
	}
}

?>

Alternatives

  • Create a separate method to handle this specific case.

‘goto’ to undefined label ‘%s’

Description

This error is displayed when a goto command has no corresponding label in the method.

This is an compilation error: it is only reported before execution.

On the other hand, a label without a goto is not reported.

Example

<?php

function foo() {
	goto A;
	A:
	goto B;
	// Not such label as B:
	
	// A orphan label
	C:
}

?>

Literal Examples

  • ‘goto’ to undefined label ‘THEN’

Alternatives

  • Create the missing label.
  • Remove the goto call.
  • Rename the goto call.

(expression)::class cannot be used in constant expressions

Description

This error appears when the value of a constant is not entirely static, but may depend on context. In this case, the self::A will only be known when the trait t is used in a class.

Example

<?php

trait T {
    const A = parent::class;
    const B = self::A::class;
}

?>

Alternatives

  • Keep values of constants simple.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

0 __HALT_COMPILER() can only be used from the outermost scope

Description

__HALT_COMPILER() stops the compiler at the exact point it is encountered; everything that follows in the file is no longer parsed as PHP code but kept as raw data, readable through the COMPILER_HALT_OFFSET constant and a file handle on the same script. Because it changes how the rest of the file is interpreted, it is only meaningful once, at the very top level of the file, and cannot be placed inside a function, a class, a conditional block, or any other nested structure. The leading “0” in this entry’s error text is a data artifact and not part of the actual PHP message.

Example

<?php

function boot() {
	__halt_compiler();
}

boot();

?>

Alternatives

  • Move the __halt_compiler() call out of the function/class/block, to the outermost level of the file.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

[] operator not supported for strings

Description

Strings and array share the bracket operator for accessing individual elements, but the append operator [] is not supported for strings.

Example

<?php

$string = 'abc';
$string[] = 'b';

?>

Alternatives

  • Use the . operator to add a string at the end of another.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

__autoload() is deprecated, use spl_autoload_register() instead

Description

The initial autoloader was a custom function, that was called whenever a class, interface or trait had to be loaded, but could not be found by PHP yet.

This approach was useful, but limited management operation: in particular, it was not possible to add more functions, or remove some of them. So, it was replaced with the spl_autoload_register() function, which add a closure to a list of autoloaders.

Example

<?php

function __autoload() {}

?>

Alternatives

  • Give another name to the __autoload function, and register it as autoloader with spl_autoload_register().
  • Remove the __autoload function.

In more recent PHP versions, this error message is now :ref:autoload()-is-no-longer-supported,-use-spl_autoload_register()-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See autoload

__autoload() is no longer supported, use spl_autoload_register() instead

Description

The initial autoloader was a custom function, that was called whenever a class, interface or trait had to be loaded, but could not be found by PHP yet.

This approach was useful, but limited management operation: in particular, it was not possible to add more functions, or remove some of them. So, it was replaced with the spl_autoload_register() function, which add a closure to a list of autoloaders.

Example

<?php

function __autoload() {}

?>

Alternatives

  • Give another name to the __autoload function, and register it as autoloader with spl_autoload_register().
  • Remove the __autoload function.

In previous PHP versions, this error message used to be :ref:autoload()-is-deprecated,-use-spl_autoload_register()-instead.

__clone method called on non-object

Description

This error signals an attempt at cloning a value that is not an object. Indeed, anything but an object triggers this error: boolean, array, string, etc.

Note that it is possible to clone a constant since PHP 8.1, so it is legit to use clone on a constant.

Example

<?php

$a = clone array();

$b = null; 
clone null;

const C = new Stdclass();
clone C;

?>

Alternatives

  • Check the data before cloning it, with is_object() or instanceof.

In more recent PHP versions, this error message is now :ref:clone():-argument-#1-($object)-must-be-of-type-object,-%s-given.

__HALT_COMPILER() can only be used from the outermost scope

Description

__HALT_COMPILER() stops the compiler at the exact point it is encountered; everything that follows in the file is no longer parsed as PHP code but kept as raw data, readable through the COMPILER_HALT_OFFSET constant and a file handle on the same script. Because it changes how the rest of the file is interpreted, it is only meaningful once, at the very top level of the file, and cannot be placed inside a function, a class, a conditional block, or any other nested structure.

Example

<?php

function boot() {
	__halt_compiler();
}

boot();

?>

Alternatives

  • Move the __halt_compiler() call out of the function/class/block, to the outermost level of the file.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

__sleep should return an array only containing the names of instance-variables to serialize.

Description

The return type of __sleep is actually array, even when it is not mentioned. Any other returned value generate this error.

Example

<?php

class X {
    function __sleep() {
        return 1;
    }
}

serialize(new X);

?>

Alternatives

  • Return an array from __sleep.
  • Add the return type array and return an array from __sleep.
  • Remove the __sleep() method.

In more recent PHP versions, this error message is now :ref:%s::__sleep()-should-return-an-array-only-containing-the-names-of-instance-variables-to-serialize.

`%s’ is not a valid mode for fopen

Description

There are several modes when opening a file, as passed with the 2nd argument. Yet, there are values and combinaisons of values thare are not possible.

Example

<?php

$fp = fopen($path, "+rw");

?>

Literal Examples

  • ‘+rw’ is not a valid mode for fopen

Alternatives

  • Use a valid open mode.

A %s with return type must return a value

Description

When a function or a method declares a return type, every return statement in its body must provide a value, unless the type accepts no returned value (void, never) or the type allows null.

Writing a bare return;, without an expression, is only valid when the declared return type permits the absence of a value. Here, int does not, so the engine cannot supply an implicit value.

This is a compile time check: it does not depend on the code being executed.

Example

<?php

function foo(): int {
    return;
}

?>

Alternatives

  • Add a value to the return statement, matching the declared return type.
  • Remove the return type, if the function is not meant to return a value.
  • Change the return type to void if the function is not meant to return a value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

A class constant must not be called class. it is reserved for class name fetching

Description

Class constants can use a lot of names, but not the name ‘class’. This is used by default to fetch the full name of the class, and there is no need to defined it.

Hence, it is not possible to define a class constant called ‘class’, case non-withstanding, as it conflict with the default constant.

Example

<?php

class X {
	const CLASS = 1;
	// the problem is case insensitive. class, Class, CLass... are all forbidden
}

?>

Alternatives

  • Use another name for that constant.

A function with return type must return a value

Description

When a function has a return type, it must have a return command in its block, which must also have an argument. In this illustration, return has no argument, so it is return void, and this is detected at compilation time.

Note that PHP lint doesn’t check the type of the returned value at linting time: any return value makes this error go away. Type is checked at execution time, and only when the expression is used: it may trigger a ‘Return value must be of type int, string returned’.

This also applies to closures, methods, arrow functions.

This error is displayed with any return that doesn’t have an argument. They might be several of them in a single function.

Example

<?php
function foo(): int {
	return ;
}

?>

Alternatives

  • Add a returned value to all the return command.
  • Check all the return commands for returned values.
  • Remove the return type.

A never returning %s does not return a value, but #[\NoDiscard] requires a return value

Description

This definition include contradicting information: the return type never means that the function will never return, so there should be no return value to handle. On the other hand, the NoDiscard attribute request the caller to do something with the returned values. This is irreconcilable.

Example

<?php

    #[\NoDiscard]
    function test(): never {
    	throw new \Exception('Error!');
    }

test();

?>

Literal Examples

  • A never returning function does not return a value, but #[\NoDiscard] requires a return value
  • A never returning method does not return a value, but #[\NoDiscard] requires a return value

Alternatives

  • Remove the never return type.
  • Remove the NoDiscard attribute.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

A never-returning %s must not return

Description

A function that never returns, aka, with the never return type, must not use the return statement.

In fact, it must use either throw, die, exit, or call another function that never returns.

This applies to methods, static methods, and any variant of closure.

The runtime-equivalent of this error is never-returning function must not implicitly return.

Example

<?php

function foo() : never {
	return 1;
}

?>

Literal Examples

  • A never-returning function must not return.

Alternatives

  • Remove the never return type.
  • Remove the return call.

A never-returning function must not return

Description

When using the never keyword, the function shall not use the return keyword. never means that the function will not return, but rather die, throw an exception, or trigger an error.

Also note that never cannot be used in a union or intersection type.

This error message applies to functions, closures and arrow functions. In PHP 8.4, a separate message applies to methods.

Example

<?php

function foo() : never {
	return true;
}

?>

Alternatives

  • Remove the return keyword in the body of the function.
  • Change the never return type to another type.

A never-returning method must not return

Description

When using the never keyword, the method shall not use the return keyword. never means that the method will not return, but rather die, throw an exception, or trigger an error.

Also note that never cannot be used in a union type.

This error message applies to methods, since PHP 8.4. Before that version, a unified message mentioning functions applied to all structures.

Example

<?php

class X {
	function foo() : never {
		return true;
	}
}

?>

Alternatives

  • Remove the return keyword in the body of the method.
  • Change the never return type to another type.

A non-numeric value encountered

Description

When the operands have to be integer, PHP tries to cast the value to an integer before perform the operation. The results varies from impossible to a simple loss of precision. In-between, some of the values cannot be partially converted, and yield this error message.

Here, the string may be converted to the integer 3, but also will loose some of the non-numeric data ‘fd’. PHP warns the user about that partial conversion, in case it doesn’t yield the expected results.

When the value cannot be converted to integer due to its type, a fatal error ‘Unsupported operand types’ is raised.

Example

<?php

var_dump("3df" % 2);

?>

Alternatives

  • Add an explicit cast to integer before usage.
  • Test if the value has an integer value before usage.

In previous PHP versions, this error message used to be :ref:a-non-well-formed-numeric-value-encountered.

A non well formed numeric value encountered

Description

When the operands have to be integer, PHP tries to cast the value to an integer before perform the operation. The results varies from impossible to a simple loss of precision. In-between, some of the values cannot be partially converted, and yield this error message.

Here, the string may be converted to the integer 3, but also will loose some of the non-numeric data ‘fd’. PHP warns the user about that partial conversion, in case it doesn’t yield the expected results.

When the value cannot be converted to integer due to its type, a fatal error ‘Unsupported operand types’ is raised.

Example

<?php

var_dump("3df" % 2);

?>

Alternatives

  • Add an explicit cast to integer before usage.
  • Test if the value has an integer value before usage.

In more recent PHP versions, this error message is now :ref:a-non-numeric-value-encountered.

A precedence rule was defined for %s::%s but this method does not exist

Description

When importing the trait, a rule was set up to resolve a method conflict between two methods, while one of them does not exist. This conflict resolution may be removed.

Example

<?php

trait A {}

trait B {
    public function bar() {}
}

class MyClass {
    use A, B {
        A::bar insteadof B;  // No bar in A
        A::bar as C;         // No bar in A too
    }
}
?>

Literal Examples

  • A precedence rule was defined for A::bar but this method does not exist

Alternatives

  • Remove the conflicting rule.
  • Create the missing method in the original trait.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

A void %s does not return a value, but #[\NoDiscard] requires a return value

Description

The #[\NoDiscard] attribute marks a function, method or closure so that the engine emits a warning whenever a caller ignores its return value. A void-returning function never produces a value to begin with, so requiring the caller to use one is a contradiction, and PHP rejects the combination at compile time.

Example

<?php

#[\NoDiscard]
function foo(): void {}

?>

Literal Examples

  • A void function does not return a value, but #[\NoDiscard] requires a return value
  • A void method does not return a value, but #[\NoDiscard] requires a return value

Alternatives

  • Remove the void return type, and actually return a meaningful value.
  • Remove the #[\NoDiscard] attribute, since there is nothing to discard.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

A void %s must not return a value

Description

A function, method or closure that uses the void return type, must not have a return expression with a parameter, in its body.

This is checked anywhere in the body of the function, at compilation time.

It is possible to use return, without any argument. It is not possible to return null, it must be without argument.

Example

<?php

function foo() : void {
    return 1;
}

?>

Alternatives

  • Remove the return expression.
  • Remove the argument of the return expression.
  • Remove the void returntype.

Abstract property %s::$%s must specify at least one abstract hook

Description

An abstract property must have at least one of its hooks declared without a body (abstract). If all hooks have implementations, the property cannot be abstract, as there is nothing left for child classes to implement.

This is a PHP 8.4 language-level restriction enforced for abstract properties with hooks. An abstract property’s purpose is to require child classes to provide an implementation, but if all hooks already have bodies, there is no requirement to fulfill.

Example

<?php

abstract class X {
    abstract public string $property {
        get { return ''; }
        set { }
    }
}

?>

Literal Examples

  • Abstract property x::$property must specify at least one abstract hook

Alternatives

  • Make at least one hook abstract by removing its body block, e.g. change get { return ''; } to get;.
  • Remove the abstract keyword from the property if all hooks should have implementations.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Abstract property hook cannot have body

Description

Property hooks, both set and get, may be made abstract by adding the keyword to the property definition. And, just like methods, abstract property hooks cannot have a body.

Example

<?php

class X {
    public abstract $property {
        get {}
    }
}

?>

Alternatives

  • Remove the abstract keyword.
  • Remove the body of the property hook.

Access level to %s::$%s must be %s (as in class %s)%s

Description

A property redeclared in a child class cannot be given a stricter visibility than the one it has in the parent class. public may be narrowed to protected or private, and protected may be narrowed to private, but never the other way, and a child cannot go further and restrict a protected property down when the parent is already public unless it stays at least as visible.

Here, X::$property is protected, and Y tries to redeclare it as private, which is a narrowing and is therefore rejected.

The trailing, optional part of the message ( or weaker) is added whenever the parent property is not public: it means the child property must use the same visibility as the parent, or something even more permissive.

Example

<?php

class X {
    protected $property;
}

class Y extends X {
    private $property;
}

?>

Literal Examples

  • Access level to Y::$property must be protected or weaker (as in class X)

Alternatives

  • Use the same visibility as the parent property.
  • Use a visibility that is the same as, or wider than, the parent property’s.
  • Remove the redeclaration in the child class, and inherit the parent property as-is.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Access level to %s::%s must be %s (as in %s %s)%s

Description

This error is emitted when a class constant is given more restrictive visibility than in the interface.

Anything in an interface is public, and so does any re-declaration in the host class.

Example

<?php

interface I {
    public const A   = 'public';
}

class X implements I {
    private const A   = 'public';
}

?>

Literal Examples

  • Access level to x::A must be public (as in interface i)
  • Access level to Z::B must be protected (as in class Y)

Alternatives

  • Remove the constant from the interface.
  • Remove the constant from the class.

Access to undeclared static property %s::$%s

Description

This error is reported when reading an undefined static property. The property must be defined before usage, or it yields a Fatal error.

This error is related to static properties: a different error is emitted for non-static properties.

Example

<?php

class X {
	public static $a = 1;
}

$x = new X;
echo X::$a; // OK
echo X::$b;

$name = 'C';
echo X::${$c}; // dynamic properties

?>

Literal Examples

  • Access to undeclared static property X::$staticProperty

Alternatives

  • Define the static property in the requested class.
  • Fix the name of the property on that class.
  • Fix the name of the class of the property.
  • Use a non-static property to handle this situation.
  • Use property_exists() or isset() to check if the property exists before using it.
  • Check if the dynamic name of the property is a string, before usage.

Access type for interface constant %s::%s must be public

Description

An method or a constant, that are defined in an interface, must appear as public in all the implementing classes. They cannot be made protected or private, as they would be no accessible.

Example

<?php

interface I {
    private const C = 1;
}

?>

Literal Examples

  • Access type for interface constant I::C must be public

Alternatives

  • Set the visibility to public in the interface.
  • Remove the visibility in the interface.
  • Remove the constant in the interface.

Access type for interface method %s::%s() must be public

Description

An method, that is defined in an interface, must appear as public. They cannot be made protected or private, as they would be no accessible.

Example

<?php

interface I {
    private function foo();
    
    protected const C = 1;
}

?>

Literal Examples

  • Access type for interface method I::foo() must be public

Alternatives

  • Set the visibility to public in the interface.
  • Remove the visibility in the interface.

Accessing static property %s::$%s as non static

Description

The property property is declared as static, and should be access with the :: operator.

Accessing that property with the -> or ?-> object operators is quite safe, as there is no confusion with the name of the property, and the object holds the name of the host class.

On the other hand, using the object operators does not provide accurate information about the actual property.

Example

<?php

class X {
    public static $property = 1;
}

$x = new X;
echo $x->property;

?>

Literal Examples

  • Accessing static property X::$property as non static

Alternatives

  • Use the :: operator to access static properties.
  • Drop the static option on the property.

Accessing static trait property %s::$%s is deprecated, it should only be accessed on a class using the trait

Description

Traits should not be used as standalone structure, but rather as a part of a class. Even for class agnostic structures, such as constants or static properties, they should be accessed via any class that uses them.

Example

<?php

trait T {
	public static $property = 1;
}

echo T::$property;
T::$property = 2;

?>

Literal Examples

  • Accessing static trait property T::$property is deprecated, it should only be accessed on a class using the trait

Alternatives

  • Find a class that use the trait, and then, access the static property from there.
  • Create a class that only use the trait, and use it. An anonymous class would do.
  • Turn the trait into a class.

Accessing static trait property %s::$%s is deprecated

Description

Traits cannot be used independently from a host class. They must be used inside a class, with the use keyword.

Until PHP 8.1, it was possible to call traits without a host class. Since 8.1, writing or reading properties in a trait is forbidden.

It is also not possible to call a method or a constant on a trait.

Example

<?php

trait T {
	public static $t = 1;
}

echo T::$t;

T::$t = 2;

?>

Literal Examples

  • Accessing static trait property T::$property is deprecated

Alternatives

  • Use the trait in a class and access its features.
  • Convert the trait into a class and access its features.

An alias (%s) was defined for method %s(), but this method does not exist

Description

When importing methods from a trait, it is possible to create a method alias: give a new name to the trait method, when it is inside a class.

PHP checks that the original method exists, before allocating the new name. When the original method doesn’t exist, PHP emits this error message.

Example

<?php

trait T {}

class X {
    use T {
        foo as bar;
    }
}
?>

Literal Examples

  • An alias (bar) was defined for method foo(), but this method does not exist

Alternatives

  • Check the name of the original method for typos.
  • Add the missing method in the trait.
  • Remove the alias.
  • Remove the method with the same name in the class, and remove the alias.

An alias was defined for %s::%s but this method does not exist

Description

When importing methods from a trait, it is possible to create a method alias: give a new name to the trait method, when it is inside a class.

PHP checks that the original method exists, before allocating the new name. When the original method doesn’t exist, PHP emits this error message.

Example

<?php

trait T {}

class X {
    use T {
        foo as bar;
    }
}
?>

Literal Examples

  • An alias was defined for X::foo but this method does not exist

Alternatives

  • Check the name of the original method for typos.
  • Add the missing method in the trait.
  • Remove the alias.
  • Remove the method with the same name in the class, and remove the alias.

An alias was defined for method %s(), which exists in both %s and %s. Use %s::%s or %s::%s to resolve the ambiguity

Description

Inside the use block of a class, an alias rule can rename a trait method without stating which trait it comes from, by writing method as alias;.

When several of the traits used by the class declare a method with that exact name, PHP has no way to decide which one the alias should refer to, since the unqualified form only works when the name is unambiguous. The class composition fails until the origin trait is made explicit.

Example

<?php

trait A {
    public function foo() {}
}

trait B {
    public function foo() {}
}

class C {
    use A, B {
        foo as bar;
    }
}

?>

Literal Examples

  • An alias was defined for method foo(), which exists in both A and B. Use A::foo or B::foo to resolve the ambiguity

Alternatives

  • Qualify the reference with the trait it should come from, as in A::foo as bar;.
  • Rename or remove the method in one of the conflicting traits so only one of them still declares it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

An iterator cannot be used with foreach by reference

Description

It is possible to use a foreach loop with a reference on the blind variable: this allows the original data to be modified.

Such feature is possible with an array as a source, but it is not possible with an iterator as a source. The iterator allows reading, but has no support for writing the individual elements it emits.

Example

<?php

    $heap = new SplMinHeap;
    foreach( $heap as &$item ) {}

?>

Alternatives

  • Turn the iterator into an array and use it.
  • Keep the blind variable per-value, and call a setter in it to update it.
  • Use objects in the iterator, it is possible to update the blind variable without the reference.

Anonymous class method %s() must not be abstract

Description

An anonymous class cannot have an abstract method, as the class is actually immediately instantiate, while abstract class, and classes that contains an abstract method cannot be instantiated.

This error was also detected previously, with a more generic error message.

Example

<?php

new class() {
    abstract function foo();
}

?>

Literal Examples

  • Anonymous class method foo() must not be abstract

Alternatives

  • Remove the abstract method.
  • Add a body to the abstract method, and remove the abstract option.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Argument #%d ($%s) must be of type %s, %s given

Description

This error is emitted when data of a wrong type is given to a typed argument.

The first parameter that fails the type constraint is reported. There might be other type failures after this one, though they are hidden by the first one encountered.

Example

<?php

function foo(int $x) {}

foo(1); // OK

foo('2'); // OK, with strict_types = 0 

foo('abc'); // not OK

?>

Literal Examples

  • Argument #1 ($x) must be of type int, string given

Alternatives

  • Pass the correct argument to the method.
  • Cast the value to the requested type.
  • Change the type in the signature of the called method.
  • Add the type in the signature of the called method.

In previous PHP versions, this error message used to be :ref:using-array_key_exists()-on-objects-is-deprecated.. In more recent PHP versions, this error message is now :ref:passing-the-encoding-as-third-parameter-is-deprecated.-use-an-explicit-zero-offset.

Argument #%d must be greater than or equal to 0

Description

This error is reported when a parameter is expected to be an integer, positive or zero. This is the case with the second argument of str_repeat().

Example

<?php
  str_repeat('abc', -1);

    // This is valid, and returns an empty string
  str_repeat('abc', 0);
?>

Literal Examples

  • str_repeat(): Argument #2 ($times) must be greater than or equal to 0

Alternatives

  • Make sure the second argument is an integer, greater or equal to zero.
  • Use intval() on the value of the second integer.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

range(): Argument #1 ($start) must be a single byte string if argument #2 ($end) is a single byte string, argument #2 ($end) converted to 0

Description

When range() produces all the values between two boundaries. These two boundaries must be of the same type, for consistency purpose. Hence, when one is a string, the second one also needs to be a string, and range() will generate all the values between these strings.

Example

<?php

range(1, 'b');

?>

Literal Examples

  • range(): Argument #1 ($start) must be a single byte string if argument #2 ($end) is a single byte string, argument #2 ($end) converted to 0

Alternatives

  • Cast the integer to a string.
  • Cast the string to an integer.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See rangeSingleByteString

Argument #1 ($value) must contain at least one element

Description

max() and min() require at least one element in the array: otherwise, the returned value could be confused with NULL.

Example

<?php

max([]);

?>

Alternatives

  • Check if the array has at least one argument before calling max() or min().
  • Add an element to the array before callign max(), and use it as a canary.

range(): Argument #2 ($end) must be a single byte string if argument #1 ($start) is a single byte string, argument #1 ($start) converted to 0

Description

When range() produces all the values between two boundaries. These two boundaries must be of the same type, for consistency purpose. Hence, when one is a one character string, the second one also needs to be a one character string, and range() generates all the values between these strings.

Example

<?php

range('c', 3);

?>

Literal Examples

  • range(): Argument #2 ($end) must be a single byte string if argument #1 ($start) is a single byte string, argument #1 ($start) converted to 0

Alternatives

  • Use another string as second argument.
  • Call range with two integers, and use chr() on each element of the array to turn them into characters.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See rangeSingleByteString

Argument of type %s will be interpreted as string in the future

Description

All of the ctype_*() functions (ctype_digit(), ctype_alpha(), ctype_alnum(), etc.) accept a string. For backward compatibility with very old PHP versions, though, when an int between -128 and 255 was passed instead, it was silently treated as a single ASCII character code (as if chr() had been called first) rather than being converted to its decimal string representation – so ctype_digit(123) tested the character chr(123) ({), not the string '123', which is a frequent source of confusion.

As of PHP 8.1, passing anything other than a string to a ctype_*() function emits this deprecation notice, warning that the value will be converted to a plain string instead of being interpreted as a codepoint once the legacy behaviour is removed.

Example

<?php

// 123 is not a string, so ctype_digit() has always treated it as an
// ASCII codepoint (like chr(123)) instead of the string "123".
var_dump(ctype_digit(123));

?>

Literal Examples

  • ctype_digit(): Argument of type int will be interpreted as string in the future

Alternatives

  • Cast the value to string explicitly if a numeric-looking value was intended, e.g. ctype_digit((string) $value).
  • Call chr() explicitly first if the intent really was to test a single ASCII codepoint, e.g. ctype_digit(chr($value)).
  • Use is_int()/is_numeric() instead of ctype_digit() when the input may not already be a string.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Argument unpacking in constant expressions is not supported

Description

It is not possible to use the ... operator in an static constant expression, with the new operator.

On the other hand, it is possible to use it inside arrays to spread the elements. It is also possible to use it in a closure definition.

Example

<?php

const A = [1,2,3];

function foo($a = new C(...A)) {}

function goo($a = [...A, ...A])) {}


?>

Alternatives

  • Access the array elements individually.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Array and string offset access syntax with curly braces is deprecated

Description

PHP used to support the curly braces {} to access elements in an array and a string. This was deprecated in PHP 7.4 and abandoned in PHP 8.0. The only operator to access an element is the square brackets [].

Example

<?php

$string = 'abc';
echo $string{1}; // b

$array = ['A', 'B', 'C'];
echo $array{1};  // B

?>

Alternatives

  • Switch to the square brackets.
  • Use the substr() function to extract one string char.

In more recent PHP versions, this error message is now :ref:array-and-string-offset-access-syntax-with-curly-braces-is-no-longer-supported.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See curly_braces

Array and string offset access syntax with curly braces is no longer supported

Description

PHP used to support the curly braces {} to access elements in an array and a string. This was deprecated in PHP 7.4 and abandoned in PHP 8.0. The only operator to access an element is the square brackets [].

Example

<?php

$string = 'abc';
echo $string{1}; // b

$array = ['A', 'B', 'C'];
echo $array{1};  // B


?>

Alternatives

  • Switch to the square brackets.
  • Use the substr() function to extract one string char.

In previous PHP versions, this error message used to be :ref:array-and-string-offset-access-syntax-with-curly-braces-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See curly_braces

Array callback has to contain indices 0 and 1

Description

PHP uses an array format to represents callback methods: it is an array with two elements. The first element is the class, and the second element is the method. To be valid, this array must also only use the index 0 and 1 (resp.) for these elements.

Also, note that this array must only have two elements.

With the explicit 0 and 1 indices, the order of the elements are not important in the array. With omitted indices, the order is important for PHP to differentiate which is the class, and which is the method.

Example

<?php

class X { 
    static function foo() {} 
}

$callback = [3 => X::class, 'foo'];

$callback();

?>

Alternatives

  • Apply array_values() to the array before using it as a callback.
  • Convert the array syntax to the new x::foo(…) syntax.
  • Convert the array syntax to the string ‘\x::foo’ syntax.
  • Remove the index in the array definition.

Array callback must have exactly two elements

Description

An array callback is an array that is used as a callback function. That structure is needed when using a method, static or not, as a callback: indeed, it requires an object or a class name, and the method name. It also does not need more elements, so two are sufficient.

Example

<?php

$a = array('a', 'b', 'c');
$a();

$e = array('d');
$e();

?>

Alternatives

  • Remove any extra elements in the array, to have only two elements.
  • Add any missing elements in the array, up to two elements.

Array to string conversion

Description

This error appears when an array is converted into a string, without a proper type cast. For example, in the illustration code, the array is directly used with echo, which requires a string, as argument. The result of this expression is Array.

This error may be a sub-part of other operations, that also requires strings. This is the second example, with implode() : the source of the error lies in the elements of the array. They are supposed to be strings, so as to be concatenated with the separator; but one of them is also an array, leading to the error.

This error is not affected by strict_types: it is always emits the same error.

Example

<?php

echo ['a'];

echo implode(',', [1, 2, ['c']]);

?>

Alternatives

  • Convert the array to a string first.
  • Extract one (or more) entries from the array, as long as they are strings.
  • Force the array to a string with cast (although it will produce the Array string).
  • Use a method that accept strings and arrays.

array_key_exists(): Argument #2 ($array) must be of type array, %s given

Description

Until PHP 8.0, it was possible to use array_key_exists() on both arrays, and objects. The objects were considered as an array, where the properties are the indices, linked to their values.

Since PHP 8.0, it is a deprecated behavior, and in a later version, PHP will make the typing more strict.

The other types, such as integer or string, are not accepted either.

Example

<?php

$object = (object) ['a' => 1]; // stdClass 
var_dump(array_key_exists('a', $object));

?>

Literal Examples

  • array_key_exists(): Argument #2 ($array) must be of type array, stdClass given
  • array_key_exists(): Argument #2 ($array) must be of type array, string given
  • array_key_exists(): Argument #2 ($array) must be of type array, int given

Alternatives

  • Cast the object to array before searching.
  • Call a method on the object to convert it to an array, before searching.
  • Create a search method, among the properties, on the object.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See array_key_existsOnObjects

array_merge() does not accept unknown named parameters

Description

array_merge() accepts one parameter, called $arrays. In fact, it is a variadic parameter, so this parameter may be repeated as needed. Yet, there is only one name for it.

When using array_merge() with a variadic argument, PHP tries to match the keys of the array with the parameters, and in this case, fails for all but one: $arrays.

The solution is to spread the array, after removing the string keys: with integer keys, PHP will not check the names.

There are several PHP native functions that behave like that: array_merge(), array_diff_key(), etc. In fact, any native method which has a variadic parameter.

PHP doesn’t emit an error when spreading an array with unknown keys in a custom function.

Example

<?php

$a = ['x' => [1], 'y' => [3]];

foo(...$a);
//array_merge() does not accept unknown named parameters
array_merge(...$a);

function foo($x, array ...$arrays) {
    print_r($arrays);
}

?>

Alternatives

  • Apply array_values() to the array that is used with array_merge().

array_merge() expects at least 1 parameter, 0 given

Description

Until PHP 7.4, array_merge() always needed at least one argument to execute. This means that using the variadic operator on an empty array yielded no argument, and then, an error.

Since PHP 7.4, array_merge() handles graciously the case of no arguments, by returning an empty array, and not more error.

This applies to array_merge() and array_merge_recursive().

Example

<?php

$array = [];

$array2 = array_merge(...[]);

?>

Alternatives

  • Check for non-empty array before using it with array_merge().

array_product(): Multiplication is not supported on type array

Description

array_product() multiplies each element in the first argument, with each other. This is a valid operation for integer, floats, numeric strings, booleans and null, as they can be cast to numbers.

This is not the case for arrays, objects, non-numeric strings or resources, which yield this warning, and are omitted in the operation.

Until PHP 8.3, the omission of invalid argument was a silent behavior.

Example

<?php

var_dump(array_product([[]] )); // returns 1

var_dump(array_product([[], 3] )); // returns 3

?>

Alternatives

  • Filter out all values in the first argument not actually numeric: aka, they can’t be cast to integer or float without error.
  • Filter out all arrays inside the first argument.

array_product(): Multiplication is not supported on type object

Description

array_product() multiplies each element in the first argument, with each other. This is a valid operation for integer, floats, numeric strings, booleans and null, as they can be cast to numbers.

This is not the case for arrays, objects, non-numeric strings or resources, which yield this warning, and are omitted in the operation.

Objects are not turned to string before being cast to numeric.

Until PHP 8.3, the omission of invalid argument was a silent behavior.

Example

<?php

var_dump(array_product([new stdClass()] )); // returns 1

var_dump(array_product([new stdClass(), 3] )); // returns 99

?>

Alternatives

  • Filter out all values in the first argument not actually numeric: aka, they can’t be cast to integer or float without error.
  • Filter out all objects inside the first argument.

array_product(): Multiplication is not supported on type string

Description

array_product() multiplies each element in the first argument, with each other. This is a valid operation for integer, floats, numeric strings, booleans and null, as they can be cast to numbers.

This is not the case for arrays, objects, non-numeric strings or resources, which yield this warning, and are omitted in the operation.

Until PHP 8.3, the omission of invalid argument was a silent behavior.

Example

<?php

var_dump(array_product(['abc'] )); // returns 1

var_dump(array_product(['33', 3] )); // returns 99

?>

Alternatives

  • Filter out all values in the first argument not actually numeric: aka, they can’t be cast to integer or float without error.
  • Filter out all strings inside the first argument, which fails the is_numeric() call.

array_sum(): Addition is not supported on type array

Description

array_sum() adds each element in the first argument, with each other. This is a valid operation for integers, floats, numeric strings, booleans and null, as they can be cast to numbers.

This is not the case for arrays, objects, non-numeric strings or resources, which yield this warning, and are omitted in the operation.

Until PHP 8.3, the omission of invalid argument was a silent behavior.

Example

<?php

var_dump(array_sum([[]] )); // returns 0

var_dump(array_sum([[], 3] )); // returns 3

?>

Alternatives

  • Filter out all values in the first argument not actually numeric: aka, they can’t be cast to integer or float without error.
  • Filter out all arrays inside the first argument.

Arrow functions on the right hand side of |> must be parenthesized

Description

The pipe operator accepts many variants of closures, such as closures, callable, arrays and first class callables. Yet, it doesn’t accept direct arrow functions: they must be placed inside parenthesis. This ensures the parser knows when to finish the returned expression, which might also include another pipe operator.

Example

<?php

    echo 'a' |> fn($a) => 1;

?>

Alternatives

  • Use a closure.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

assert.active INI setting is deprecated

Description

assert.active is a legacy INI directive that dates back to the pre-PHP 7 implementation of assert(), where assertions could be toggled on or off at runtime through several assert.* INI settings.

Since PHP 7, assertion behavior is primarily controlled by the zend.assertions directive, which supports three modes: 1 (generate and execute code, development mode), 0 (generate code, but skip execution at runtime), and -1 (do not generate code, production mode). assert.active became redundant, only affecting whether assert() calls are executed at all, and is now deprecated.

The deprecation notice is triggered whenever assert.active is set to a falsy value, either in php.ini or through ini_set().

Example

<?php

ini_set('assert.active', '0');

?>

Alternatives

  • Use the zend.assertions directive to control whether assertions are compiled and executed.
  • Remove ini_set()/ini_get() calls involving assert.active from the code.

In more recent PHP versions, this error message is now :ref:assert.bail-ini-setting-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See assert

assert.bail INI setting is deprecated

Description

assert.bail is a legacy INI directive from the pre-PHP 7 implementation of assert(). When enabled, it terminated script execution as soon as a failed assertion was encountered, instead of letting the script continue.

This behavior is redundant with throwing an AssertionError (the default behavior since PHP 7 when assert.exception is enabled), which already interrupts execution unless the exception is caught. As part of the general cleanup of the legacy assertion configuration, assert.bail is now deprecated.

The deprecation notice is triggered whenever assert.bail is set to a truthy value, either in php.ini or through ini_set().

Example

<?php

ini_set('assert.bail', '1');

?>

Alternatives

  • Rely on the AssertionError exception thrown by failed assertions (controlled by assert.exception) to stop execution, and catch it where appropriate.
  • Remove ini_set()/ini_get() calls involving assert.bail from the code.

In previous PHP versions, this error message used to be :ref:assert.active-ini-setting-is-deprecated. In more recent PHP versions, this error message is now :ref:assert.exception-ini-setting-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See assert

assert.callback INI setting is deprecated

Description

The php.ini directive assert.callback is deprecated, alongside several features from the assert functions. It should not be set anymore in the code.

Note that a call to ini_get() will not generate the warning: only the ini_set().

Example

<?php

ini_set('assert.callback', 1);

?>

Alternatives

  • Remove the call to assert.callback and its dependencies.

assert.exception INI setting is deprecated

Description

assert.exception controls whether a failed assert() throws an AssertionError (the default since PHP 7) or falls back to the legacy behavior of emitting a warning and continuing execution.

Disabling exceptions for assertions revives pre-PHP 7 behavior that is inconsistent with the rest of the language, where failures are normally reported through exceptions or errors. As part of the cleanup of the legacy assert.* configuration, this directive is now deprecated.

The deprecation notice is triggered whenever assert.exception is set to a falsy value, either in php.ini or through ini_set().

Example

<?php

ini_set('assert.exception', '0');

?>

Alternatives

  • Keep assert.exception enabled (the default) and catch AssertionError where a failed assertion needs to be handled instead of propagating.
  • Remove ini_set()/ini_get() calls involving assert.exception from the code.

In previous PHP versions, this error message used to be :ref:assert.bail-ini-setting-is-deprecated. In more recent PHP versions, this error message is now :ref:assert.warning-ini-setting-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See assert

assert.warning INI setting is deprecated

Description

assert.warning is a legacy INI directive that, when assert.exception is disabled, controls whether a failed assert() call emits an E_WARNING. It is part of the pre-PHP 7 assertion configuration that predates AssertionError.

Since this directive only has an effect together with the also-deprecated assert.exception, and there is no equivalent replacement to keep emitting a custom warning message, it is now deprecated as well. Once removed in PHP 9, disabling it will no longer be possible.

The deprecation notice is triggered whenever assert.warning is set to a falsy value, either in php.ini or through ini_set().

Example

<?php

ini_set('assert.warning', '0');

?>

Alternatives

  • Rely on the AssertionError exception thrown by failed assertions instead of the legacy warning-based reporting.
  • Remove ini_set()/ini_get() calls involving assert.warning from the code.

In previous PHP versions, this error message used to be :ref:assert.exception-ini-setting-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See assert

Assignments can only happen to writable values

Description

With the list() operator, the right part of the => operator must be a variable or equivalent. The corresponding value on the right part of the assignation will be stored there, so it has to be a data container. It is possible to use a variable, property (static or not), an array element or an array append.

The same error may happen when the property is not available: this may be the case with a nullsafe operator.

This is valid with or without the index part, in the list() call.

Example

<?php

// short array syntax. The left part is not an array, but a list()
[1] = [2];
['a' => 1] = ['a' => 2];

list('a' => 1) = array('a' => 2);

// ?-> may be returning null, and not a valid container.
[$foo?->bar->baz] = ['bar'];

?>

Alternatives

  • Use a variable.
  • Use an array append.
  • Use a a property.

Attempt to assign property “%s” on null

Description

null is not an object, and it can’t be used as such. Until PHP 8.0, the engine would automatically create a stdClass object, and replace the null value with it. This is not the case anymore.

Example

<?php

$a = null;

$a->b = 1;

?>

Literal Examples

  • Attempt to assign property “b” on null

Alternatives

  • Instantiate any object and replace null with it.
  • Explicitly instantiate a stdClass object and replace null with it.
  • Remove the property usage.
  • Use another variable to use this property.

In previous PHP versions, this error message used to be :ref:creating-default-object-from-empty-value.

Attempt to read property “%s” on %s

Description

This error reports that a non-object was used with an object syntax. Non-objects are integers, floats, strings, null, booleans, etc.

This is a warning, so PHP will continue execution, using null as a result of this operation.

Example

<?php

$integer = 1;
var_dump($integer->a);

$array = [3];
var_dump($array?->a);

?>

Literal Examples

  • Attempt to read property “a” on int
  • Attempt to read property “a” on array
  • Attempt to read property “a” on float
  • Attempt to read property “a” on string
  • Attempt to read property “a” on bool

Alternatives

  • Remove the use of the property.
  • Add a type to the underlying variable, to ensure it is an object.
  • Check the variable is an object.

Attempt to unset static property %s::$%s

Description

It is not possible to unset a static property.

This applies to typed and not typed static properties. It also only applies to static properties that are already set, such as in the illustration: PHP complains about uninitialized state first, and later, about removing static properties.

This does not apply to properties, which may be removed.

Example

<?php

class X {
    public static $y = 1;
    public static int $z;
}

//Attempt to unset static property X::$x
unset(X::$y);

//Attempt to unset static property X::$z
unset(X::$z);
X::$z = 2;
//Attempt to unset static property X::$x
unset(X::$z);


?>

Literal Examples

  • Attempt to unset static property X::$x

Alternatives

  • Set the property to null.
  • Set the property to a value that represents removal.

Attribute “%s” cannot target %s (allowed targets: %s)

Description

Attributes are built with a specific target, and may not be applicable to any structure. For example, the native ReturnTypeWillChange targets only methods, and not properties.

With a custom structure, the error is shown when requesting an instance of the attribute. Otherwise, this error remains silent, and the structure may be used without error.

With a PHP native attribute, the engine decides when it makes use of it.

Example

<?php

// example with a native PHP attribute
class Foo
{
    #[ReturnTypeWillChange]
    public int $bar;
}

#[Attribute(Attribute::TARGET_FUNCTION | Attribute::TARGET_METHOD)]
class X { }

// the object is created. It may be used without error.
$ref = new ReflectionObject(new #[X] class() { });
$attr = $ref->getAttributes()[0];

try {
    $attr->newInstance();
} catch (\Throwable $e) {
    print $e->getMessage();
}

?>

Alternatives

  • Remove the attribute restrictions.
  • Update the attribute to target the requested feature.
  • Remove the attribute from the forbidden feature.
  • Create another the attribute for the feature.

Attribute class “%s” not found

Description

This error reports that a class was not found. This is also focusing on attribute classes.

Class are reported as not found when they are used, so this error message is displayed when the attribute is actually used in the code, by calling the getInstance reflection. An attribute might exists without its underlying class, as long as it is not instanciated.

Example

<?php

#[X] 
function f() { }

$ref = new \ReflectionFunction('\f');

try {
    $ref->getAttributes()[0]->newInstance();
} catch (\Error $e) {
    var_dump($e->getMessage());
}
?>

Literal Examples

  • Attribute class “Deprecated” not found

Alternatives

  • Check spelling and namespace for that class.
  • Create the associated class.
  • Avoid using getInstance() on that attribute.

auto_detect_line_endings is deprecated

Description

The auto_detect_line_endings ini directive tells fgets(), file() and fgetss() to look at the first few lines of a file to detect the classic Mac OS (pre-OS X) \r-only line ending convention, and adjust the line-splitting logic accordingly.

Classic Mac OS line endings are essentially extinct, so keeping this detection logic around adds a runtime cost and a behavioral surprise for very little benefit. The directive is deprecated, and setting it to a truthy value now raises a deprecation notice; it will be removed entirely in PHP 9.0.

Example

<?php

ini_set('auto_detect_line_endings', '1');

$fp = fopen('data.txt', 'r');
$line = fgets($fp);

?>

Alternatives

  • Leave auto_detect_line_endings at its default (disabled) value.
  • If \r-only line endings must be supported, read the whole file with file_get_contents() and split it with a regular expression that matches \r\n, \r or \n, such as preg_split('/\r\n|\r|\n/', $contents).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Automatic conversion of false to array is deprecated

Description

The array syntax $variable[index] is only available for arrays and strings. Yet, false is an edge case: PHP used to convert automatically, and silently, the boolean to array, when that syntax was used. This is called autovivification.

The other boolean, true behaves the same way, with a different error message.

This feature is used to initialize variables with false, and then convert it to array as needed.

Since PHP 8.1, it is a deprecated behavior.

Example

<?php

$variable = false;
$variable[0] = 1;
// $variable is now an array

class X {
    public bool|array $property = false;
}

$x = new X;
$x->property['d'] = 3;

?>

Alternatives

  • Use an empty array as default value.
  • Test the type of the variable before using it as an array.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See autoInitializeArrayFromBool

Automatic fetching of PostgreSQL connection is deprecated

Description

Many pg_* functions, such as pg_query() and pg_query_params(), accept a PostgreSQL connection as their first argument, but this parameter used to be optional: when omitted, PHP implicitly reused the last connection opened with pg_connect() or pg_pconnect().

This implicit default_link behavior makes it easy to accidentally query the wrong connection when a script opens more than one, and it forces the pgsql extension to keep a hidden, mutable global state. As of PHP 8.1.0, relying on this default connection is deprecated, and an explicit connection must be passed instead.

Example

<?php

pg_connect('host=localhost dbname=test');

// The connection argument is omitted: PHP implicitly reuses
// the last connection opened by pg_connect()/pg_pconnect().
$result = pg_query('SELECT 1');

?>

Alternatives

  • Store the resource/object returned by pg_connect() or pg_pconnect() and pass it explicitly as the first argument to every pg_* function used afterwards.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See pg_query

Bad class name in the catch statement

Description

A catch clause lists one or more class or interface names (possibly joined with |) that the caught exception must match. Those names have to be resolvable to a concrete class at compile time.

The pseudo-class static refers to the class the method was actually called on, which is only known at runtime, not at compile time. Since PHP needs to know the exact catch types while compiling the try/catch block, static cannot be used there, even though it is otherwise allowed as a return type or inside the method body.

Example

<?php

class Test
{
    public function method()
    {
        try {
            foo();
        } catch (static $e) {
        }
    }
}

?>

Literal Examples

  • Bad class name in the catch statement

Alternatives

  • Use the real class name instead of static.
  • Use self if the intent is to catch the class in which the method is defined.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

break operator accepts only positive integers

Description

break indicates the number of nested loop to break from. The minimum is 1. 0 would be a no operation, and shall be skipped. Negative numbers or decimals make no sense.

Example

<?php

$a = [];
foreach($a as $b) {
    break 0;
    
}

?>

Alternatives

  • Remove the continue command.
  • Remove the 0.

Call to %s %s::%s() from global scope

Description

This error reports that the requested method exists, but is not available from the context of call. Here, the method is private and should only be called from within its definition class.

There are distinct messages for calling an unknown method, or calling a protected method.

Example

<?php

class X {
    public function foo() {}
    private function goo() {}
}

$x = new X;
$x->goo();

?>

Literal Examples

  • Call to private x::goo() from global scope

Alternatives

  • Call a public method on that class.
  • Check for typos in the name of the method.
  • Change the visibility of the method, to be able to call it.

Call to %s %s::%s() from invalid

Description

A private method shall only be called from within its own class. It cannot be called from another class, or from the global space. In particular, the method cannot be called directly, or indirectly: for example, new X indirectly calls the __construct method.

A protected method shall only be called from within its own class, or any of it parent or children. It cannot be called from another non-related class, or from the global space. In particular, the method cannot be called directly, or indirectly: for example, new X indirectly calls the __construct method.

A public method may be called from anywhere in the code.

Example

<?php

class X {
    //This is also the case with proctected __construct
    private function __construct() {}

    static public function factory() {
        return new X();
    }
}

//This is not possible
$x = new X();

?>

Literal Examples

  • Call to private method X::__construct() from global scope

Alternatives

  • Check that the call to the method, and the visibility of the method are compatible.

In more recent PHP versions, this error message is now :ref:call-to-%s-method-%s::%s()-from-%s%s.

Call to %s %s::__destruct() from global scope during shutdown ignored

Description

During PHP shutdown, destructors are called for remaining objects. When a __destruct() method is invoked from global scope (i.e. not as part of object destruction triggered by the garbage collector or script end), PHP emits this warning and ignores the call.

This typically happens when a register_shutdown_function() callback creates an object whose destructor is called during the final cleanup phase. The object is destroyed immediately, but the invocation from global scope is considered invalid.

The warning ensures that destructors are only called in their expected context: as part of object lifetime management, not from arbitrary global code.

Example

<?php

class X {
    public function __destruct() {
        echo "Destroying\n";
    }
}

register_shutdown_function(function() {
    $x = new X;
});

?>

Literal Examples

  • Call to public X::__destruct() from global scope during shutdown ignored
  • Call to protected X::__destruct() from global scope during shutdown ignored

Alternatives

  • Move the logic from __destruct() into a regular method and call it explicitly before the object is destroyed.
  • Avoid creating objects inside shutdown functions if you rely on their destructor behavior.
  • Use a dedicated lifecycle method instead of relying on __destruct() for cleanup logic.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Call to %s method %s::%s() from %s%s

Description

A private method shall only be called from within its own class. It cannot be called from another class, or from the global space. In particular, the method cannot be called directly, or indirectly: for example, new X indirectly calls the __construct method.

A protected method shall only be called from within its own class, or any of it parent or children. It cannot be called from another non-related class, or from the global space. In particular, the method cannot be called directly, or indirectly: for example, new X indirectly calls the __construct method.

A public method may be called from anywhere in the code.

Example

<?php

class X {
    //This is also the case with proctected __construct
    private function __construct() {}

    static public function factory() {
        return new X();
    }
}

//This is not possible
$x = new X();

?>

Literal Examples

  • Call to private method X::__construct() from global scope

Alternatives

  • Check that the call to the method, and the visibility of the method are compatible.

In previous PHP versions, this error message used to be :ref:call-to-%s-%s::%s()-from-invalid.

Call to a member function %s() on %s

Description

This error happens when the object syntax is used on a string. A string is a scalar type, and cannot hold method, properties nor constants. The type of the variable should be checked before usage. This also happens with the nullsafe operator, which only protects against NULL used as an object.

Example

<?php

'a'?->foo();

$string = 'abc';
$string->foo();

?>

Literal Examples

  • Call to a member function foo() on string
  • Call to a member function foo() on int
  • Call to a member function foo() on null

Alternatives

  • Check the type of the object before usage.

Call to undefined function %s()

Description

This error is displayed when the called function is not defined. There are many places in the code where a function may be defined: in the PHP core engine, in PHP extensions, in dependencies, in the current file, in an included file. Also, since PHP 8.0, a function, disabled with the disable_functions directive, is shown as undefined, rather than forbidden.

Example

<?php

undefined_function();

?>

Literal Examples

  • Call to undefined function undefined_function()
  • Call to undefined function shell_exec()
  • Call to undefined function mb_substr()

Alternatives

  • The function has not been written in the code.
  • The function has not been included in the code before being called.
  • The function name has a typo.
  • The function is not defined in the current PHP version.
  • The function is not defined in any PHP extension version.
  • The function is not defined the current namespace, or the global namespace.
  • The use expression, used to import that function from another namespace, misses the function keyword: use foo as A instead of use function foo as A.
  • The function is actually a closure: a $ is missing: $variable(), instead of variable().
  • This is actually a constant, and extra () were added.
  • The function was disabled with disable_functions.

In previous PHP versions, this error message used to be :ref:%s()-has-been-disabled-for-security-reasons.

Call to undefined function each()

Description

each() used to be a PHP native function. It was deprecated in PHP 7.4, and is undefined since PHP 8.0.

Example

<?php

$array = ['a', 'b'];
while(list($key, $value) = each($array)) {
    print "$key => $value\n";
}

?>

Alternatives

  • Downgrade to PHP 7.x.
  • Use yield.
  • Use yield from.
  • Use foreach().

In previous PHP versions, this error message used to be :ref:the-each()-function-is-deprecated.-this-message-will-be-suppressed-on-further-calls.

Call to undefined function exit()

Description

exit and die used to be language constructures, until PHP 8.4. Then, they could not be used in a dynamic function call, such as shown here. Indeed, language constructs are not accessible with that syntax.

Since PHP 8.4, die and exit are defined as functions, and shall be used with the dynamic call feature.

Example

<?php

$function = 'exit';
$function();

?>

Alternatives

  • Upgrade to PHP 8.4.

Call to undefined function

Description

This error appears when calling a function that is not defined.

There should be a function definition in the code, and that definition must be included in the code before it is called. The presence of a function may be tested with the function_exists() function.

The function may be defined in a PHP extension, or its core: then, the function has no explicit definition. Its existence may be checked with a call to get_defined_function(), which lists all the functions, at the execution point.

A function may be disabled in the PHP.ini, using the disabled_functions directive. Then, the function is totally unknown by PHP, and it may even be redefined.

Language constructs, such as exit and die, are not functions, and some features, such as calling them from a string, is not possible until PHP 8.4.

The function might be defined in a different namespace, or its import might be missing.

Example

<?php

// calling a function before it is defined
foo();

function foo() {}

try {
	//Uncaught Error: Call to undefined function \exit()
    $s = 'exit';
    $s();
} catch(Error) {
    print "No such function as $s";
}

?>

Alternatives

  • Check the spelling of the function name.
  • Check the version of PHP, or its extensions: some functions are defined in specific versions, or later.
  • Check the namespace of the called function: it might not be available in the current namespace, or in the global namespace.
  • Check the use expression at the beginning of the file: the import expression might be missing.
  • Use the function_exists() function before calling a function whose name is stored in a variable.
  • Use a try/catch around the function call, and catch Error (not exceptions).

Call to undefined method %s::%s()

Description

This message is emitted when no method with the requested name could be found on the class, or its parents or traits.

Calling from another class’s context yields a distinct message.

Example

<?php

class X {
    function foo() {}
}

$x = new X;
$x->goo();

?>

Literal Examples

  • Call to undefined method x::goo()

Alternatives

  • Check the spelling of the method name.
  • Check if the object supports this method.
  • Check if there are the valid trait name import (use in a class), to define the method.
  • Check if the method is still available in the current setup (PHP version, components and library versions…).
  • Check if the magic method __call() is not missing in the object’s class.

Callables of the form ["%s

Description

PHP’s callable array syntax is documented as [$objectOrClass, 'methodName']: the first element gives the object or class, the second is a plain method name. The engine, however, has always also accepted a second element that is itself a compound 'Class::method' string, silently ignoring or double-checking the class given by the first element. This form only ever worked through call_user_func(), is_callable() and similar reflective APIs – it was never invocable through the direct $callable() syntax – so it belongs to the family of ‘partially supported callables’.

As of PHP 8.2, resolving such an array emits Callables of the form ["%s", "%s"] are deprecated, with the two placeholders filled with the class name resolved from the first element and the full compound string from the second. Plain callables such as 'Class::method' or [$objectOrClass, 'method'] are not affected.

Example

<?php

class Foo {
    public static function bar() {
        return 'bar called';
    }
}

// The first element already resolves 'Foo', and the second element
// repeats it inside a compound 'Class::method' string.
$callable = ['Foo', 'Foo::bar'];

var_dump(call_user_func($callable));

?>

Literal Examples

  • Callables of the form [“Foo”, “Foo::bar”] are deprecated

Alternatives

  • Drop the redundant class prefix from the second element and use the plain method name: [$objectOrClass, ‘method’].
  • If a fully qualified callable is preferred, use the string form ‘Class::method’ directly instead of an array.
  • Use first-class callable syntax (PHP 8.1+), e.g. Foo::bar(…), when the target is known at the call site.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling %pS() for static method %pS::%pS() does not need an object parameter

Description

ReflectionMethod::invoke() and ReflectionMethod::invokeArgs() accept an object as their first argument to use as $this inside the invoked method. For a static method there is no $this, so that object is simply ignored — but silently ignoring it hides a likely mistake, such as invoking the wrong method or forgetting the target is static. PHP 8.6 deprecates passing a non-null object in this case.

Example

<?php

class TestClass {
    private static function staticMethod() {
        echo "Called staticMethod()\n";
    }
}

$method = new ReflectionMethod(TestClass::class, 'staticMethod');
$instance = new TestClass();

$method->invoke($instance);

?>

Literal Examples

  • Calling ReflectionMethod::invoke() for static method TestClass::staticMethod() does not need an object parameter
  • Calling ReflectionMethod::invokeArgs() for static method TestClass::staticMethod() does not need an object parameter

Alternatives

  • Pass null as the object argument when invoking a static method: $method->invoke(null).
  • If you meant to call an instance method, check that $method really refers to it.

In more recent PHP versions, this error message is now :ref:calling-%ps()-with-a-given-object-that-is-not-an-instance-of-the-class-this-property-was-declared-in-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling %pS() with a 1st argument which is not null or an object is deprecated

Description

ReflectionProperty::setValue() sets a static property when called as setValue(null, $value): the 1st argument is not used to locate a static property, since it has no associated object, but it is still type-checked.

Prior to this deprecation, PHP silently accepted any value as the 1st argument in that case, as it was simply discarded. Since PHP 8.3, passing a value that is neither null nor an object as the 1st argument is deprecated, in order to make the accepted signature consistent with its declared ?object type.

Example

<?php

class X {
    public static int $count = 0;
}

$prop = new ReflectionProperty(X::class, 'count');

// deprecated: the 1st argument is ignored for static properties,
// but it must still be null or an object
$prop->setValue('ignored', 42);

var_dump(X::$count);

?>

Literal Examples

  • Calling ReflectionProperty::setValue() with a 1st argument which is not null or an object is deprecated

Alternatives

  • Pass null explicitly as the 1st argument when setting a static property: setValue(null, $value).
  • If the property is not static, pass the actual object instance as the 1st argument instead of an unrelated value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling %pS() with a given object that is not an instance of the class this property was declared in is deprecated

Description

ReflectionProperty::setValue() and ReflectionProperty::setRawValue() take the target object as their first argument. When that object is not an instance of the class (or a subclass of it) the property was declared on, the write silently falls back to creating a dynamic property on the unrelated object instead of failing. PHP 8.6 deprecates this mismatch, since it almost always indicates the wrong $propInfo or the wrong object was used.

Example

<?php

class TestClass {
    public $pub2 = 5;
}

#[AllowDynamicProperties]
class AnotherClass {
}

$instanceWithNoProperties = new AnotherClass();
$propInfo = new ReflectionProperty('TestClass', 'pub2');

$propInfo->setValue($instanceWithNoProperties, 'NewValue');

?>

Literal Examples

  • Calling ReflectionProperty::setValue() with a given object that is not an instance of the class this property was declared in is deprecated
  • Calling ReflectionProperty::setRawValue() with a given object that is not an instance of the class this property was declared in is deprecated

Alternatives

  • Only call setValue() / setRawValue() with an object that is an instance of the class the ReflectionProperty was created for.
  • Use instanceof to verify the object before calling setValue() if it is not known statically.

In previous PHP versions, this error message used to be :ref:calling-%ps()-for-static-method-%ps::%ps()-does-not-need-an-object-parameter.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling %pS() with a single argument is deprecated

Description

ReflectionProperty::setValue() accepts an object as its 1st argument and the new value as its 2nd argument. Static properties have no associated object, so PHP historically allowed calling setValue() with a single argument (the value only) to set a static property.

Since this single-argument form is ambiguous with the two-argument form used for instance properties, it is deprecated as of PHP 8.3. The 1st argument must now be passed explicitly, using null to mean “this is a static property”.

Example

<?php

class X {
    public static int $count = 0;
}

$prop = new ReflectionProperty(X::class, 'count');

// deprecated: the object argument is missing
$prop->setValue(42);

var_dump(X::$count);

?>

Literal Examples

  • Calling ReflectionProperty::setValue() with a single argument is deprecated

Alternatives

  • Call setValue(null, $value) instead of setValue($value) to set a static property.
  • For instance properties, always pass the object as the 1st argument: setValue($object, $value).
  • Use ReflectionClass::setStaticPropertyValue() as an alternative way to set a static property by reflection.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling %s() on an object is deprecated

Description

prev(), current(), next() and reset() where php native functions used to navigate in arrays. They also applied to objects, although this is an accidental feature. Nowadays, using object with these functions is deprecated.

Example

<?php

$object = (object) ['a' => 1];

echo current($object);

?>

Literal Examples

  • Calling prev() on an object is deprecated
  • Calling next() on an object is deprecated
  • Calling reset() on an object is deprecated
  • Calling current() on an object is deprecated

Alternatives

  • Cast the object to an array, and store it in a variable before using the mentioned functions.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See passingObjectIsDeprecated

Calling %s() with 2 arguments is deprecated,

Description

This is the generic shape of a family of deprecation notices introduced by the Deprecate functions with overloaded signatures RFC. Several built-in functions used to accept more than one call shape, distinguished only by how many arguments were passed, such as pg_fetch_result(), pg_field_prtlen() and pg_field_is_null() (2-argument form relying on an implicit row cursor) or stream_context_set_option() (2-argument form taking a whole options array instead of a single wrapper/option/value triple).

As of PHP 8.4, calling any of these functions with the specific, older argument count that made the overload ambiguous emits this deprecation notice, naming the function and pointing to its replacement. The exact wording of the second half of the message (after the comma) depends on the function.

Example

<?php

$conn = pg_connect('host=localhost dbname=test');
$result = pg_query($conn, 'SELECT id, name FROM users');

// 2-argument form: implicit row cursor instead of an explicit $row
echo pg_fetch_result($result, 'name'), "\n";

?>

Literal Examples

  • Calling pg_fetch_result() with 2 arguments is deprecated, use the 3-parameter signature with a null $row parameter instead
  • Calling stream_context_set_option() with 2 arguments is deprecated, use stream_context_set_options() instead
  • Calling pg_field_is_null() with 2 arguments is deprecated, use the 3-parameter signature with a null $row parameter instead

Alternatives

  • Check the specific function’s documentation for its replacement: a dedicated function (e.g. stream_context_set_options()) or the newer, explicit argument count (e.g. always passing $row to pg_fetch_result()).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling %s(resource $stub

Description

Phar::setStub() (and PharData::setStub()) historically accepted two different signatures: a plain string $stub, or a resource $stub together with an int $length telling PHP how many bytes to read from the stream. Overloaded signatures like this make the function harder to reason about and to type-check.

As of PHP 8.3, calling the method with the (resource $stub, int $length) form is deprecated in favour of the single string $stub signature; the resource variant will be removed in PHP 9.0.

Example

<?php

$phar = new Phar('/tmp/test.phar');

$stream = fopen('php://memory', 'r+');
fwrite($stream, "<?php __HALT_COMPILER(); ?>");
rewind($stream);

// Passing a resource plus an explicit length is the overloaded,
// now-deprecated signature.
$phar->setStub($stream, 20);

fclose($stream);

?>

Literal Examples

  • Calling Phar::setStub(resource $stub, int $length) is deprecated
  • Calling PharData::setStub(resource $stub, int $length) is deprecated

Alternatives

  • Read the resource into a string first and pass that string: $phar->setStub(stream_get_contents($stub)).
  • If the resource is a file, read its contents with file_get_contents() instead of fopen()+fread().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling a function “readonly” is deprecated

Description

readonly has been a semi-reserved word since PHP 8.1, when it was introduced as a modifier for readonly properties and classes. It could still be used as the name of a function, class, or constant, and PHP even special-cased a global function literally called readonly() so that WordPress, which ships one, would keep working.

PHP 8.6 deprecates calling such a function, as part of a broader effort to fully reserve readonly for the language. The deprecation notice is emitted every time the function is called, not when it is declared.

Example

<?php

function readonly() {
    return 'not a property modifier';
}

echo readonly();

?>

Literal Examples

  • Calling a function “readonly” is deprecated

Alternatives

  • Rename the function to something that is not readonly, e.g. readonlyValue() or getReadonly().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, a global function literally named readonly() could be declared and called without any warning, as a compatibility carve-out for WordPress. As of PHP 8.6, calling it emits a deprecation notice, in preparation for readonly becoming a fully reserved word.](Previously, a global function literally named readonly() could be declared and called without any warning, as a compatibility carve-out for WordPress. As of PHP 8.6, calling it emits a deprecation notice, in preparation for readonly becoming a fully reserved word.)

Calling DatePeriod::__construct(string $isostr, int $options = 0) is deprecated,

Description

DatePeriod::__construct() has always accepted several unrelated sets of arguments: a start DateTimeInterface, an interval and either an end date or a number of recurrences, or, as a third overload, a single ISO 8601 recurring interval string (such as R4/2026-01-01T00:00:00Z/P1D).

Overloaded constructors that change meaning based on the number and type of arguments are error-prone and hard to document accurately. The ISO 8601 string overload is being split out into its own named constructor, and calling the constructor directly with a string is deprecated.

Example

<?php

$period = new DatePeriod('R4/2026-01-01T00:00:00Z/P1D');

foreach ($period as $date) {
    echo $date->format('Y-m-d'), PHP_EOL;
}

?>

Alternatives

  • Use DatePeriod::createFromISO8601String() instead of passing the ISO 8601 recurring interval string to the constructor.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling dba_fetch() with $dba at the 3rd parameter is deprecated

Description

dba_fetch() historically accepted the database handle as its 3rd argument, behind an optional $skip argument used to select a duplicate key: dba_fetch(string $key, int $skip, resource $dba).

Every other dba_*() function takes the database handle as its 2nd argument, right after the key, so this older signature was inconsistent with the rest of the extension. Calling dba_fetch() with the handle in the 3rd position is now deprecated in favor of the consistent signature.

Example

<?php

$dba = dba_open('/tmp/test.db', 'c', 'flatfile');

$value = dba_fetch('some_key', 0, $dba);

?>

Alternatives

  • Pass the database handle as the 2nd argument instead: dba_fetch(string $key, resource $dba, int $skip = 0).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling FFI::cast() statically is deprecated

Description

cast(), new() and type() are instance methods of the object returned by FFI::cdef() or FFI::load(): each loaded C definition scope has its own set of types, so casting or instantiating should happen on that specific instance.

For convenience, PHP also allowed calling these methods statically as FFI::cast(), FFI::new() and FFI::type(), in which case they implicitly operated on an anonymous, definition-less scope. This static shortcut is ambiguous about which set of C declarations is being used, and is now deprecated.

Example

<?php

$ffi = FFI::cdef('typedef struct { int x; int y; } point;');

$mem = $ffi->new('point');

$casted = FFI::cast('int', $mem);

?>

Alternatives

  • Call cast() on the FFI instance returned by FFI::cdef() or FFI::load() instead of calling it statically: $ffi->cast(...).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ffiCastStaticDeprecated

Calling FFI::new() statically is deprecated

Description

new(), cast() and type() are instance methods of the object returned by FFI::cdef() or FFI::load(): each loaded C definition scope has its own set of types, so allocating a new value should happen on that specific instance.

For convenience, PHP also allowed calling these methods statically as FFI::new(), FFI::cast() and FFI::type(), in which case they implicitly operated on an anonymous, definition-less scope. This static shortcut is ambiguous about which set of C declarations is being used, and is now deprecated.

Example

<?php

FFI::cdef('typedef struct { int x; int y; } point;');

$mem = FFI::new('point');

?>

Alternatives

  • Call new() on the FFI instance returned by FFI::cdef() or FFI::load() instead of calling it statically: $ffi->new(...).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ffiNewStaticDeprecated

Calling FFI::type() statically is deprecated

Description

type(), cast() and new() are instance methods of the object returned by FFI::cdef() or FFI::load(): each loaded C definition scope has its own set of types, so resolving a type name should happen on that specific instance.

For convenience, PHP also allowed calling these methods statically as FFI::type(), FFI::cast() and FFI::new(), in which case they implicitly operated on an anonymous, definition-less scope. This static shortcut is ambiguous about which set of C declarations is being used, and is now deprecated.

Example

<?php

FFI::cdef('typedef struct { int x; int y; } point;');

$type = FFI::type('point');

?>

Alternatives

  • Call type() on the FFI instance returned by FFI::cdef() or FFI::load() instead of calling it statically: $ffi->type(...).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ffiTypeStaticDeprecated

Calling get_class() without arguments is deprecated

Description

get_class() used to allow its usage without an argument. Then, it would return the current class context, at compile time. Hence, in the code here, it used to return x, may it be called from x or y.

This behavior is not allowed anymore, and will be removed in PHP 9.

Note that calling get_class without an argument was different from calling get_class with the null value.

Example

<?php

class X {
	function foo() {
		echo get_class();         // x
		echo get_class($this);    // y

		// echo get_class(null);  // Type error
	}
}

class Y extends X {}

echo (new Y)->foo();

?>

Alternatives

  • Use the CLASS constant to get the name of the class at compile time.
  • Use the get_class($this) call, to get the name of the class at execution time.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See get_classWithoutArgument

Calling get_parent_class() without arguments is deprecated

Description

Using null as a parameter for the get_class() and get_parent_class() native call is deprecated since PHP 8.3. Using the null value defaulted to the current class, so it is possible to use $this instead.

Example

<?php

get_parent_class();

?>

Alternatives

  • Use $this as an argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See get_classWithoutArgument

Calling IntlCalendar::set() with more than 2 arguments is deprecated,

Description

IntlCalendar::set() (and the procedural intlcal_set()) used to accept between 2 and 6 arguments: a single field/value pair, or up to a year, month, day, hour, minute and second all at once. Squeezing several different call shapes into one method made the signature hard to read and to type correctly.

Calling it with more than 2 arguments — i.e. using it to set several date or time components at once — is now deprecated in favor of two dedicated methods.

Example

<?php

$calendar = IntlCalendar::createInstance('UTC');

$calendar->set(2026, 0, 1, 12, 30, 0);

?>

Alternatives

  • Use IntlCalendar::setDate() to set the year, month and day, or IntlCalendar::setDateTime() to also set the hour, minute and second.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling IntlGregorianCalendar::__construct() with more than 2 arguments is deprecated,

Description

IntlGregorianCalendar::__construct() (and the procedural intlgregcal_create_instance()) used to accept many different combinations of arguments: a timezone, a locale, or up to a year, month, day, hour, minute and second, all disambiguated at runtime from the number and type of arguments given.

Calling the constructor with more than 2 arguments — i.e. using it to build a date directly from year/month/day(/hour/minute/second) components — is now deprecated in favor of two dedicated, unambiguous factory methods.

Example

<?php

$calendar = new IntlGregorianCalendar(2026, 0, 1, 12, 30, 0);

?>

Alternatives

  • Use IntlGregorianCalendar::createFromDate() to build a calendar from a year, month and day, or IntlGregorianCalendar::createFromDateTime() to also set the hour, minute and second.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling ldap_connect() with Oracle-specific arguments is deprecated

Description

When PHP’s LDAP extension is built against Oracle Instant Client, ldap_connect() gained two extra, Oracle-specific parameters ($wallet and $wallet_passwd, plus an $auth_mode flag) on top of the hostname and port, to authenticate using an Oracle wallet.

This Oracle-only overload is now deprecated along with the rest of ldap_connect()’s multi-argument forms, in favor of a dedicated function that only exists in Oracle-enabled builds.

Example

<?php

$ldap = ldap_connect('ldap.example.com', 389, '/path/to/wallet', 'wallet_password', 1);

?>

Alternatives

  • Use ldap_connect_wallet() to connect with an Oracle wallet instead of passing wallet arguments to ldap_connect().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling ldap_exop() with more than 4 arguments is deprecated, use ldap_exop_sync() instead

Description

ldap_exop() used to serve two purposes at once: sending an LDAP extended operation and, when called with 5 or 6 arguments, also synchronously waiting for the response and returning its data and OID through reference parameters (&$response_data, &$response_oid).

Mixing the asynchronous, low-level operation with an optional synchronous, high-level convenience wrapper in a single overloaded function made the API harder to reason about. Calling ldap_exop() with more than 4 arguments is now deprecated in favor of a dedicated synchronous function.

Example

<?php

$ldap = ldap_connect('ldap://ldap.example.com');
ldap_bind($ldap);

ldap_exop($ldap, LDAP_EXOP_WHO_AM_I, null, null, $response_data, $response_oid);

?>

Alternatives

  • Use ldap_exop_sync() when you need to send the operation and immediately read back its response data and OID.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling mb_check_encoding() without argument is deprecated

Description

mb_check_encoding() normally takes a string (or an array of strings) and checks whether it is valid in a given encoding. It could also be called with no arguments at all, in which case the documentation claimed it would check $_GET, $_POST, $_SERVER, and other superglobal input for encoding validity.

In practice, this zero-argument form was never fully implemented: it only reported whether any invalid byte sequences had been detected so far during the request, rather than actually checking all of the input again. Because this behavior is confusing and unreliable, calling mb_check_encoding() without an argument is deprecated as of PHP 8.1.0.

Example

<?php

// Called without any argument.
var_dump(mb_check_encoding());

?>

Alternatives

  • Pass the value to check explicitly, e.g. mb_check_encoding($value, 'UTF-8').
  • Validate each relevant superglobal entry individually instead of relying on the implicit whole-request check.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_check_encoding

Calling pg_fetch_result() with 2 arguments is deprecated,

Description

pg_fetch_result() originally accepted two different call shapes: a 3-argument form giving the row and field explicitly, and a 2-argument form that omitted the row and implicitly fetched from an internal, auto-advancing row cursor. Mixing an explicit-row API and a stateful, cursor-based one in a single overloaded function made the behavior harder to predict, especially when other calls interleaved with the cursor’s position.

As of PHP 8.4, calling pg_fetch_result() with only 2 arguments is deprecated in favor of always passing 3 arguments, using null explicitly for $row when the old auto-advancing behavior is wanted.

Example

<?php

$conn = pg_connect('host=localhost dbname=test');
$result = pg_query($conn, 'SELECT id, name FROM users');

// 2-argument form: relies on an implicit "current row" cursor
echo pg_fetch_result($result, 'name'), "\n";

?>

Literal Examples

  • Calling pg_fetch_result() with 2 arguments is deprecated, use the 3-parameter signature with a null $row parameter instead

Alternatives

  • Call pg_fetch_result() with 3 arguments, passing null as $row to keep the auto-advancing cursor behavior explicitly.
  • Track the row index yourself and always pass it explicitly, instead of relying on the implicit cursor.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling ReflectionMethod::__construct() with 1 argument is deprecated,

Description

ReflectionMethod::__construct() originally accepted two call shapes: two arguments, new ReflectionMethod($classOrObject, $methodName), or a single string combining both as "Class::method". Overloading the constructor based on argument count made its signature harder to type and to document.

PHP 8.3 added ReflectionMethod::createFromMethodName() as a dedicated factory method for the single-string form. As of PHP 8.4, calling the constructor with only 1 argument is deprecated in favor of that factory method.

Example

<?php

// Single string argument, combining class and method with '::'
$method = new ReflectionMethod('DateTime::format');

echo $method->getName(), "\n";

?>

Literal Examples

  • Calling ReflectionMethod::__construct() with 1 argument is deprecated, use ReflectionMethod::createFromMethodName() instead

Alternatives

  • Use ReflectionMethod::createFromMethodName(‘Class::method’) instead of new ReflectionMethod(‘Class::method’).
  • Use the 2-argument constructor, new ReflectionMethod($classOrObject, $methodName), when the class and method are already available separately.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Calling static trait method %s::%s is deprecated

Description

Traits cannot be used independently from a host class. They must be used inside a class, with the use keyword.

Until PHP 8.1, it was possible to call traits without a host class. Since 8.1, calling a trait method is deprecated.

It is also not possible to call a method or a property on a trait.

Example

<?php

trait T {
	public static function foo() { echo __METHOD__; };
}

t::foo();

?>

Literal Examples

  • Calling static trait method T::foo is deprecated

Alternatives

  • Use the trait in a class and access its features.
  • Convert the trait into a class and access its features.

Calling stream_context_set_option() with 2 arguments is deprecated,

Description

stream_context_set_option() originally accepted two call shapes: a 4-argument form setting a single wrapper/option/value triple, and a 2-argument form that instead took a whole nested ["wrapper"]["option"] = value array in place of the last three arguments. Overloading a single function with such different shapes made the signature hard to express with proper types.

PHP 8.3 added a dedicated stream_context_set_options() function for the array form. As of PHP 8.4, calling stream_context_set_option() with only 2 arguments is deprecated in favor of that new function.

Example

<?php

$context = stream_context_create();

// 2-argument form: context + a full ["wrapper"]["option"] = value array
stream_context_set_option($context, ['http' => ['method' => 'POST']]);

?>

Literal Examples

  • Calling stream_context_set_option() with 2 arguments is deprecated, use stream_context_set_options() instead

Alternatives

  • Use stream_context_set_options($context, $options) instead of stream_context_set_option($context, $options) for the array form.
  • Use the 4-argument form, stream_context_set_option($context, $wrapper, $option, $value), to set a single option.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Can’t inherit abstract function %s::%s() (previously declared abstract in %s)

Description

In PHP 7.0 and 7.1, it was not possible to inherit an abstract class. In PHP 7.2, it was made possible.

Example

<?php

abstract class A           { abstract function bar(stdClass $x);  }
abstract class B extends A { abstract function bar($x): stdClass; }

//   Fatal error: Can't inherit abstract function A::bar()
?>

Literal Examples

  • Can't inherit abstract function B::bar() (previously declared abstract in A)

Alternatives

  • Upgrade to PHP 7.2 or later.
  • Remove the abstract keyword.
  • Remove the method.

Can’t use function return value in write context

Description

A write context is any position that needs an actual variable slot to write to, remove, or bind a reference to: the left side of an assignment, the target of unset(), a foreach-by-reference variable, and similar. A function call only produces a value; it does not designate a storage location, so the engine has nothing to write to, unset, or reference, and rejects the call outright at compile time, before it is ever executed.

Example

<?php

function getValue() {
	return 5;
}

getValue() = 3;

unset(getValue());

?>

Alternatives

  • Store the return value in a variable first, then use the variable in the write context: $v = getValue(); unset($v);

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Can’t use method return value in write context

Description

A write context is any position that needs an actual variable slot to write to, remove, or bind a reference to: the left side of an assignment, the target of unset(), a foreach-by-reference variable, and similar. This is the same restriction as for plain function calls, reported with a distinct message because the engine recognizes method calls (instance calls with ->, and static calls with ::) as a separate kind of AST node from ordinary function calls. A method call only produces a value; it does not designate a storage location, so it is rejected at compile time, before the method is ever invoked.

Example

<?php

class Foo {
	public function getValue() {
		return 5;
	}
}

(new Foo())->getValue() = 3;

unset((new Foo())->getValue());

?>

Alternatives

  • Store the return value in a variable first, then use the variable in the write context: $v = (new Foo())->getValue(); unset($v);

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Can’t use nullsafe operator in write context

Description

The nullsafe operator is only available for reading, not writing. Aka, it cannot be used on the left side of an assignation.

The nullsafe operator replaces any non-existing property with a null value: that value is not an object, and cannot handle properties on its own.

This limitation applies to assignations, short assignations, such as .=, +=, etc., pre and post incrementations ++$a->b, and references arguments.

Example

<?php

$x = new stdClass();

$x?->a = 1;

?>

Alternatives

  • Use the -> operator for writing operations.

Can only flip string and integer values, entry skipped

Description

array_flip() converts values into keys and keys into values. The former values undergo a process to convert them to valid keys, which are strings or integers.

In general, non-scalar values cannot be converted, and are skipped: this is the case of arrays.

In particular, string or integer backed enumerations and stringable objects are not converted to strings. This applies with or without strict_types.

Example

<?php

array_flip([[1], E::A, new X])

enum E : string {
    case A = 'a';
}

class X implements Stringable {
    function __toString() {
        return 'X';
    }
}


?>

Alternatives

  • Force the type to be string when building the array.
  • Apply a converting method with array_map(), before calling array_filter.

Can only throw objects

Description

The throw keyword operates on exceptions, which are always objects. So, it is not possible to throw other types, such as integers, strings or arrays.

Example

<?php

throw 1;

?>

Alternatives

  • Use throw new Exception().
  • Use throw new Error().
  • Use throw $object, where $object contains an error or an exception.
  • Use throw ($object), where $object contains an error or an exception.

Cannot %s readonly property %s::$%s from %s%s

Description

Until PHP 8.4, the assignation (first and final), of a readonly property had to be executed in the definition class. In the illustration, this means that $property must be assigned in the X class. This was applied all the time, without consideration for the visibility of the property.

Since PHP 8.4, visibility allowing, a readonly property may be defined in any of the child classes too.

Example

<?php

class X {
	public readonly int $property;
}

class Y extends X {
    function __construct() {
        $this->property = 5;
    }
}

$x = new Y;
echo $x->property;

?>

Literal Examples

  • Cannot initialize readonly property X::$property from scope Y
  • Cannot initialize readonly property X::$property from global scope

Alternatives

  • Upgrade to PHP 8.4.
  • Remove the readonly option.

Cannot access %s const %s::%s

Description

Constants have visibility, which restrict access to the defining class (private), or the class and its children (protected).

Example

<?php

class X {
    private const A = 1;
}

echo X::A;

?>

Literal Examples

  • Cannot access private constant X::A

Alternatives

  • Relax the visibility constraint to protected or public to make the constant available to the calling context.
  • Create a method to access the value of the constant.
  • Extends the class and change the visibility level of the constant.

In more recent PHP versions, this error message is now :ref:cannot-access-%s-constant-%s::%s.

Cannot access %s constant %s::%s

Description

Class constants have visibility, which restrict access to the defining class (private), or the class and its children (protected).

Example

<?php

class X {
    private const A = 1;
}

echo X::A;

?>

Literal Examples

  • Cannot access private constant X::A

Alternatives

  • Relax the visibility constraint to protected or public to make the constant available to the calling context.
  • Create a method to access the value of the constant.
  • Extends the class and change the visibility level of the constant.

In previous PHP versions, this error message used to be :ref:cannot-access-%s-const-%s::%s.

Cannot access %s property %s::$%s

Description

Properties have visibility, which restrict access to the defining class (private), or the class and its children (protected).

This applies to static and normal properties.

Example

<?php

class X {
    private string $property = 'abc';
}

echo (new X)->property;

?>

Literal Examples

  • Cannot access private property X::$property
  • Cannot access protected property X::$property

Alternatives

  • Relax the visibility constraint to protected or public to make the property available to the calling context.
  • Create a method to access the value of the property.
  • Extends the class and change the visibility level of the property from protected to public. This has no effect for private.

Cannot access offset of type %s in isset or empty

Description

In an array notation, the offset may be a variable, or any container. Yet, it must be a string or an integer; and when applied to an string, it must be an integer.

This error is reported when a value which type is not cast to integer (such as null, boolean, float) or string is used. Here, it is an object.

It is also a specific message, emitted when the error happens as an argument of isset or empty. Both function have an error suppression feature, and yet, this error is reported.

Example

<?php

// illustration example
$object = new Stdclass;
$string = 'abc';

echo isset($string[$object]);

?>

Literal Examples

  • Cannot access offset of type stdClass in isset or empty

Alternatives

  • Check the type of the index before using it in the array notation.
  • Check the type of the underlying object, using the array notation.
  • Cast the index to (string) or (int) when using it in the array notation.

Cannot access offset of type %s on %s

Description

In an array notation, the offset may be a variable, or any container. Yet, it must be a string or an integer; and when applied to an string, it must be an integer.

This error is reported when a value which type is not cast to integer (such as null, boolean, float) or string is used. Here, it is an object.

Note that a class that extends ArrayAccess interface allows the manipulation of any kind of key: this is possible, yet rare.

This error message has been extended to more types than string : for example, array.

Example

<?php

// illustration example
$object = new Stdclass;
$string = 'abc';

echo $string[$object];

$array = [];
echo $array[$object];

function foo(A $a) {
    $string = 'abc';
    echo $string[$a];
}

?>

Literal Examples

  • Cannot access offset of type stdClass on string
  • Cannot access offset of type stdClass on array

Alternatives

  • Check the type of the index before using it in the array notation.
  • Check the type of the underlying object, using the array notation.
  • Cast the index to (string) or (int) when using it in the array notation.

Cannot access parent:: when current class scope has no parent

Description

The trait X has a property, which is typed with a relative type: parent. Yet, as a trait, there is no parent class possible.

This situation is solved when the trait is use d in a class, as long as the class has a parent. But it is not possible directly on the trait.

This error is now covered with the upcoming deprecation of direct manipulation of static properties on a trait, without using its host class.

This error is also possible with self. It is not possible with static, as properties can’t be typed static.

This error is also possible on interfaces.

Example

<?php

trait X {
    public static parent $property;
}

try {
    Test::$property = new stdClass;
} catch (Error $e) {
    echo $e->getMessage(), PHP_EOL;
}

?>

Alternatives

  • Do not use parent or self keywords in interfaces. Use an actual class name.
  • Do not use parent or self keywords in traits. Use an actual class name.
  • Do not use parent or self keywords in enumerations. Use an actual class name.

Cannot access parent:: when no class scope is active

Description

parent refers to the parent class of the one. As such, parent can only be used inside a class or a trait.

Example

<?php

static::x;

?>

Alternatives

  • Move the code inside a method, in a trait or a class.
  • Use the full name of the class that should be used.

Cannot access self:: when no class scope is active

Description

self refers to the curent class of the one. As such, self can only be used inside a class or a trait.

Example

<?php

static::x;

?>

Alternatives

  • Move the code inside a method, in a trait or a class.
  • Use the full name of the class that should be used.

Cannot access static:: when no class scope is active

Description

static refers to the class that was called to access the class elements (constants, method, properties..). As such, static can only be used inside a class or a trait.

Example

<?php

static::x;

?>

Alternatives

  • Move the code inside a method, in a trait or a class.
  • Use the full name of the class that should be used.

In more recent PHP versions, this error message is now :ref:cannot-use-"static"-when-no-class-scope-is-active.

Cannot access trait constant %s::%s directly

Description

Traits cannot be used indepently from a host class. They must be used inside a class, with the use keyword.

It is also not possible to call a method or a property on a trait.

Trait constants were introduced after direct access to trait features was banned, so there was no time where accessing a trait constant was possible, unlike trait properties or methods.

Example

<?php

trait T {
	public static const C = 1;
}

echo T::C;

?>

Literal Examples

  • Cannot access trait constant T::C directly

Alternatives

  • Use the trait in a class and access its features.
  • Convert the trait into a class and access its features.

In previous PHP versions, this error message used to be :ref:traits-cannot-have-constants.

Cannot acquire reference to $GLOBALS

Description

It is not possible to create a reference to a the superglobal $GLOBALS. The property is readonly and cannot be changed. On the other hand, references are never readonly, and provide read and write access to the data. PHP has no way to check that the reference is readonly. Hence, references on readonly properties are not allowed.

Example

<?php

// Cannot acquire reference to $GLOBALS
$a = &$GLOBALS;

?>

Alternatives

  • Remove the readonly option on the property.
  • Remove the reference to the property.

Cannot acquire reference to readonly property %s::$%s

Description

It is not possible to create a reference to a readonly property. The property is readonly and cannot be changed. On the other hand, references are never readonly, and provide read and write access to the data. PHP has no way to check that the reference is readonly. Hence, references on readonly properties are not allowed.

Example

<?php

class Test {
    public readonly int $property;

    public function init() {
        $this->property = 1;
    }
}

$test = new Test;
$test->init();

try {
    foreach ($test as &$property) {}
} catch (Error $e) {
    echo $e->getMessage(), \n;
}

?>

Literal Examples

  • Cannot acquire reference to readonly property Test::$property

Alternatives

  • Remove the readonly option on the property.
  • Remove the reference to the property.

Cannot add element to the array as the next element is already occupied

Description

This error appears when the largest PHP integer has been used as an index in an array. When appending a new item in the array, PHP calculates the largest index, and adds one. Though, in this situation, it is not possible anymore to create a new integer, since the last one was used.

This error appears when a value was stored out of the way, yet the array is appended later.

Example

<?php

$array = [0 => 'a', PHP_INT_MAX => 'b'];
$array[] = 3;

?>

Alternatives

  • Avoid using PHP_INT_MAX as index in the array.
  • Assign the value with an explicit index, rather than an append.

Cannot append to $GLOBALS

Description

$GLOBALS is not a regular array: each of its entries is really a reference to a variable in the global scope, identified by its name. Appending with the empty-bracket operator, which would normally pick the next integer key, has no matching global variable to bind to, so PHP 8.1 turned this previously-meaningless operation into a compile-time error instead of silently creating a global variable literally named “0”.

Example

<?php

$GLOBALS[] = 'value';

?>

Alternatives

  • Assign to an explicit, named key instead: $GLOBALS[‘name’] = ‘value’;

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See GLOBALSAppend

Cannot append to WeakMap

Description

WeakMap is a map from objects to values, and each key is an object. Unlike an array, it has no automatic integer index, so the [] syntax, which appends a new element, cannot be used with it.

To add an entry, give the object that will be the key: $map[$object] = $value.

Example

<?php

$map = new WeakMap();

// A WeakMap is keyed by objects, so there is no next integer key to append to
$map[] = 'Damien';

?>

Literal Examples

  • Cannot append to WeakMap

Alternatives

  • Use an object as the key: $map[$object] = $value, instead of $map[] = $value.
  • If you need a list of values with integer keys, use a regular array instead of a WeakMap.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot apply #[AllowDynamicProperties] to enum %s

Description

The attribute AllowDynamicProperties has no meaning when used with an enumeration, even as enums can define properties.

Example

<?php

#[AllowDynamicProperties]
enum E {}

?>

Literal Examples

  • Cannot apply #[AllowDynamicProperties] to enum e

Alternatives

  • Do not use the attribute on an enumeration.

Cannot apply #[AllowDynamicProperties] to interface %s

Description

The attribute AllowDynamicProperties has no meaning when used with a interface, even as interface can define properties. Apply it to any class that implements the interface.

Example

<?php

#[AllowDynamicProperties]
interface I {}

?>

Literal Examples

  • Cannot apply #[AllowDynamicProperties] to interface i

Alternatives

  • Use the attribute on the class that implements the interface.

Cannot apply #[AllowDynamicProperties] to readonly class %s

Description

Readonly classes are classes whose properties are set once, and never changed afterwards. The readonly option may be added to the individual property, or globally, at the class level.

Since PHP 8.1, dynamic properties are deprecated. A dynamic property is a property which is used at execution time, aka $object->dynamic = 2;, and has no explicit definition in the class block. Dynamic properties are created, yet they don’t have any option, including the readonly option. In consequence, #[AllowDynamicProperties] and readonly at the class level are incompatible.`.

Example

<?php

#[AllowDynamicProperties]
readonly class X {
	private $property = 1;
}

?>

Literal Examples

  • Cannot apply #[AllowDynamicProperties] to readonly class x

Alternatives

  • Remove readonly from the class, and add it to all the properties in the class.
  • Create a readonly property with a another class which use the #[AllowDynamicProperties] attribute.
  • Create a readonly property with an array type, and use it to process the dynamic entries.
  • Remove the #[AllowDynamicProperties] attribute.

Cannot apply #[AllowDynamicProperties] to trait %s

Description

The attribute AllowDynamicProperties has no meaning when used with a trait, even as traits can defined properties. Apply it to any class that uses the trait.

Example

<?php

#[AllowDynamicProperties]
trait T {}

?>

Literal Examples

  • Cannot apply #[AllowDynamicProperties] to trait t

Alternatives

  • Use the attribute on the class that use the trait.

Cannot apply attributes to multiple constants at once

Description

It is not possible to use attributes on global constants, when several constants are defined at the same time. That syntax is possible with class constants, but not with global constants.

Example

<?php

#[Foo]
const A = 1,
      B = 2;

?>

Alternatives

  • Split the constant definitions, and apply the same attribute to each of them.
  • Convert the global constants to class constants.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot assign %s to class constant %s::%s of type

Description

Since PHP 8.3, constants may have a type specification. In this case, the default value must match the requested type.

In particular, there is not type juggling, so type has to match exactly.

Example

<?php

class X {
    const int A = '3';
}
?>

Literal Examples

  • Cannot assign string to class constant x::A of type int

Alternatives

  • Drop the default value.
  • Adapt the default value to the requested type.
  • Drop the type of the constant.

Cannot assign %s to property %s::$%s of type %s

Description

This error signals that the wrong type of data was used when assigning a value to a property. When a type is set on a property, it is always expected to receive that type.

Example

<?php

class X {
    public int $property;
}

$x = new X;
$x->property = 'de';

?>

Literal Examples

  • Cannot assign string to property X::$property of type int

Alternatives

  • Add the type of this value to the type description.
  • Remove the type on the property.
  • Cast the value to the correct type.

Cannot assign %s to reference held by property %s::$%s of type %s

Description

When a variable holds a reference to a property, it also has to satisfy the type constraints. Here, by using a typed reference, the $var variable looks like another local variable, but it is in fact typed.

Example

<?php

class X {
    public static int $int = 1;
}

$var = &X::$int;

$var = 'abc';
?>

Literal Examples

  • Cannot assign string to reference held by property X::$int of type int

Alternatives

  • Remove the type from the property.
  • Use a valid value to the property.
  • Remove the initial link to the property until the value is of the correct type.

Cannot assign an empty string to a string offset

Description

It is possible to access an individual character inside a string, and replace it with another character.

On the other hand, it is not possible to remove that character by using an empty string. The only allowed modification is a replacement: one character replace another character.

In fact, PHP will only use the first character, when trying to modify an offset with a string longer than one character.

Example

<?php

$string = 'ab d';
$string[2] = 'c';  // add c in the right place

$string[2] = '';  // error

$string[2] = 'Cdef';  // only sets the c

?>

Alternatives

  • Use substr() to cut the string before and after, then concatenate them.
  • Replace the character with a space.

Cannot assign reference to non referenceable value

Description

It is possible to assign values by references, only when the right operand is already stored in a variable, or similar.

Example

<?php

list(&$x) = [1, 2]; 

$array = [1,2];
list(&$x, ) = $array 

?>

Alternatives

  • Store the operand in a variable (or equivalent).
  • Assign values individually.

Cannot assign to array(), use [] instead in %s

Description

The left array is actualy the list instruction. With that, PHP tries to assign each values of the array on the right to their same position on the left. In this case, there is an array, and it is not possible to assign directly to an array: it could be assigned to an element of that array, just not the whole array.

Example

<?php

[array($a)] = [array(42)];
var_dump($a);

?>

Alternatives

  • Remove the array() on the left.
  • Remove the [] on the left.
  • Replace the = with an == operator, to convert this into an assignation.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot assign to array(), use [] instead

Description

array(…) is a language construct that builds a new array value; it does not designate a destructurable container the way list(…) or the short […] syntax do, so it can never appear on the left-hand side of an assignment. This dedicated error exists to catch the common mistake of typing array(…) where list(…) was meant, and points directly to the short-syntax alternative.

Example

<?php

$data = [1, 2];
array($a, $b) = $data;

?>

Alternatives

  • Use list(): list($a, $b) = $data;
  • Use the short destructuring syntax: [$a, $b] = $data;

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot auto-initialize an array inside property %s::$%s of type %s

Description

The last command is using the array syntax on the property $property. In fact, the property is of type bool.

If this was a variable, this would be tolerated, but it cannot happen on a property, which enforces the types at all times.

Indeed, if the union type bool|array is used, the automatic conversion to array is reported.

When the type of the property is string, the array syntax is partially supported: it works with integer index, and fails with strings.

Example

<?php

class X {
    public bool $property = false;
}

$x = new X;
$x->property[4] = 3;

?>

Literal Examples

  • Cannot auto-initialize an array inside property X::$property of type bool
  • Cannot auto-initialize an array inside property X::$property of type int

Alternatives

  • Convert the type of the property to array.
  • Create a distinct property, with the array type, to use the array syntax.

cannot be 0

Description

The third argument of range() is the step: the amount to progress for each element, compared to the previous one. When that step is null, the range() function always creates the same element, with no chance to finish. This cannot be 0.

Example

<?php

$interval = range(10, 20, 0);

?>

Alternatives

  • Use a value strictly non-zero.

cannot be a class constant

Description

Class constants must be defined in classes, enums, traits or interfaces. They cannot be created dynamically, nor with the define() function.

Example

<?php
define('foo::bar', 1);
define('::', 1);
?>

Alternatives

  • Define the class constant in a class.
  • Define the class constant in a trait.
  • Define the class constant in a interface.
  • Define the class constant in a enum.
  • Define the global constant, and use it as a value for the class constant.

cannot be empty

Description

The provided parameter is of the valid type, but cannot be left empty.

Example

<?php

print_r(explode('', 'abc')); // Not possible with an empty delimiter

print_r(str_split(1, 'abc')); 

?>

Alternatives

  • When parsing data, make sure that the separator is not empty.

In previous PHP versions, this error message used to be :ref:empty-delimiter. In more recent PHP versions, this error message is now :ref:must-not-be-empty.

cannot be LC_ALL

Description

The 3rd argument ($category) of dcgettext() and the 5th argument ($category) of dcngettext() cannot be LC_ALL.

Example

<?php

dcgettext('a', 'item', LC_ALL);
dcngettext('b', 'item', 'item2', 1, LC_ALL);

?>

Alternatives

  • Use one of the valid categories: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL.

cannot be null when argument #1 ($objectOrMethod) is an object

Description

The ReflectionMethod class requires 2 argument: the first with the class, and the second with the method name. Passing one argument is deprecated.

Example

<?php

$x = new X();
$method = new ReflectionMethod($x);

?>

Alternatives

  • Adds the name as second argument method.

Cannot bind an instance to a static closure, this will be an error in PHP 9

Description

The Closure::bind() method gives the scope of execution of a closure. And a static closure uses no scope, so the bind() method fails.

Example

<?php
    $closure = static function () { return __METHOD__;};

    $closure->bindTo(new Stdclass());
    $closure();

?>

Alternatives

  • Remove the static option on the closure.
  • Remove the call to bind().

In previous PHP versions, this error message used to be :ref:cannot-bind-an-instance-to-a-static-closure.

Cannot bind an instance to a static closure

Description

The Closure::bind() method gives the scope of execution of a closure. And a static closure uses no scope, so the bind() method fails.

Example

<?php
    $closure = static function () { return __METHOD__;};

    $closure->bindTo(new Stdclass());
    $closure();

?>

Alternatives

  • Remove the static option on the closure.
  • Remove the call to bind().

In more recent PHP versions, this error message is now :ref:cannot-bind-an-instance-to-a-static-closure,-this-will-be-an-error-in-php-9.

Cannot bind method %s::%s() to object of class %s, this will be an error in PHP 9

Description

A closure created from a non-static method ($obj->method(...) or Closure::fromCallable()) can only be bound to an instance of the class the method belongs to, or one of its subclasses. Binding it to an object of an unrelated class, as done above with an instance of Y while the method is defined on X, is not allowed.

Since PHP 8.5, this operation already emitted an E_WARNING and the bind silently failed, returning null. It is now deprecated and will become a fatal error in PHP 9.0.

Example

<?php

class X {
    public function method() {
        return __METHOD__;
    }
}

class Y {}

$x = new X;
$fn = $x->method(...);
$fn2 = Closure::bind($fn, new Y, Y::class);
var_dump($fn2);

?>

Literal Examples

  • Cannot bind method X::method() to object of class Y, this will be an error in PHP 9

Alternatives

  • Bind the closure to an instance of the class that declares the method, or one of its subclasses.
  • If the method should work on unrelated classes too, extract the logic into a standalone function or a trait shared by both classes.

In previous PHP versions, this error message used to be :ref:cannot-bind-method-%s::%s()-to-object-of-class-%s.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See closure

Cannot bind method %s::%s() to object of class %s

Description

This error is reported when a closure is called on an object which is not identical to the the type of the original object.

Example

<?php

class X {
    public function method() {    }
}

class Y { }

$closure = Closure::fromCallable([new X, 'method']);
$closure->call(new B);

?>

Literal Examples

  • Cannot bind method A::M() to object of class C

Alternatives

  • Make sure the new object is of the same type as the original support one.

In more recent PHP versions, this error message is now :ref:cannot-bind-method-%s::%s()-to-object-of-class-%s,-this-will-be-an-error-in-php-9.

Cannot call %pS() dynamically

Description

A handful of built-in functions, such as compact(), extract(), func_get_args(), func_get_arg() and func_num_args(), work by inspecting the calling scope directly. Because of that, they can only be called by writing their name literally in the source code; they cannot be called dynamically, for example through a variable holding the function name, call_user_func(), or the first-class callable syntax. This restriction predates PHP 8.6: the Closure produced by $fn(...) above is created successfully, but throws this Error the moment it is actually invoked.

PHP 8.6 introduces Partial Function Application (the ? and ... placeholders), which is built on the same compiler as first-class callable syntax. Using a placeholder call such as compact(?, ?) on one of these scope-dependent functions hits the same restriction, but does so immediately, while the partial-application expression itself is being compiled, rather than only when the resulting closure is later called.

Example

<?php

$fn = 'compact';

// First-class callable syntax applied to a variable function name
$partial = $fn(...);
$partial('a', 'b');

?>

Literal Examples

  • Cannot call compact() dynamically
  • Cannot call extract() dynamically
  • Cannot call func_get_args() dynamically

Alternatives

  • Call the function by writing its literal name in the source, instead of through a variable, callback, or Partial Function Application.
  • For compact()/extract(), pass the variables or array explicitly instead of relying on the calling scope.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [The restriction and its message text are unchanged. PHP 8.6 only changes when it is reported for these functions when used with Partial Function Application placeholders: the error now surfaces while compiling the partial-application expression, instead of only when the resulting Closure is later called.](The restriction and its message text are unchanged. PHP 8.6 only changes when it is reported for these functions when used with Partial Function Application placeholders: the error now surfaces while compiling the partial-application expression, instead of only when the resulting Closure is later called.)

Cannot call constructor

Description

When there is no need to define a constructor, it may be skipped. Then, PHP creates the object without that initial method call.

On the other hand, if a child class makes an explicit call to the parent constructor, then on of the parents MUST have a constructor.

In the example here, the child class explicitly calls the parent constructor, but it doesn’t exists.

Example

<?php

class X {}

class Y extends X {
	function __construct() {
		parent::__construct();
	}
}

?>

Alternatives

  • Create an empty constructure in a parent, to ensure its calling.
  • Skip the call to the parent constructor in the child: it is useless anyway.

Cannot change default fetch mode while fetching

Description

PDOStatement::setFetchMode() refuses to run while the statement is in the middle of fetching a row. This happens when PDO::FETCH_CLASS is used and the constructor of the target class receives the statement object itself (via the constructor arguments) and calls setFetchMode() on it before the current fetch() call has finished.

Prior to this guard, such a re-entrant call could corrupt the statement’s internal fetch state and lead to a use-after-free. PDO now detects the situation and throws an Error instead.

Example

<?php

class Test {
    public string $val1;
    public string $val2;

    public function __construct(mixed $stmt) {
        if ($stmt instanceof PDOStatement) {
            // Re-entrant call -- the statement is still fetching the current row
            $stmt->setFetchMode(PDO::FETCH_CLASS, self::class, [$this->val2]);
        }
    }
}

$stmt = $pdo->prepare('SELECT val1, val2 FROM example');
$stmt->setFetchMode(PDO::FETCH_CLASS, Test::class, [$stmt]);
$stmt->execute();

$stmt->fetch();

?>

Alternatives

  • Call setFetchMode() before fetch()/fetchAll() starts, never from within a constructor triggered by the fetch itself.
  • Avoid passing the live PDOStatement as a constructor argument to the fetched class; pass the data it needs instead.
  • If the fetch mode must change mid-iteration, finish consuming the current row first, then call setFetchMode() before the next fetch().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot combine named arguments and argument unpacking

Description

In PHP 8.0, named parameters were introduced. They allow the naming of a parameter, which is used later to assign the value to the parameter, based on names and not on position.

Initially, it was not possible to mix unpacked arguments from an array and parameters.

Example

<?php

function foo(...$params) { 
    print_r($params); 
}

$args = [1, 2];
foo(...$args, params: 1);

?>

Alternatives

  • Upgrade PHP version to 8.1 or later.
  • Move the arguments in the array, and unpack it.

Cannot combine nullsafe operator with Closure creation

Description

PHP 8.1 introduced the first class callable syntax, using (...) to create a Closure from a method or function call, without invoking it.

The nullsafe operator ?-> short-circuits the call when the object is null, evaluating to null instead. Combined with Closure creation, this would mean the expression sometimes returns a Closure and sometimes null, which is not a coherent result for the engine to compile.

This combination is therefore forbidden, and detected at compile time.

Example

<?php

class X {
    public function foo() {}
}

$x = new X();

$closure = $x?->foo(...);

?>

Alternatives

  • Use the -> operator instead of ?->, making sure the object is never null at that point.
  • Check the object for null explicitly, before creating the Closure.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot combine partial application and unpacking

Description

PHP 8.5 extends the first-class callable syntax with partial application: a lone … placeholder as the last argument of a call turns it into a Closure over the remaining, not-yet-supplied parameters. The same … token is already used for argument unpacking (spreading an array’s values as arguments), so a call that both spreads an array and ends with the placeholder is ambiguous between “spread this array, then partially apply” and a typo, and PHP rejects it outright.

Example

<?php

function add($a, $b, $c) {
	return $a + $b + $c;
}

$args = [1, 2];

$curried = add(...$args, ...);

?>

Alternatives

  • Wrap the call in an explicit closure instead: $curried = fn($c) => add(…$args, $c);

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot create Closure as attribute argument

Description

It is possible to use ... in a function call, but not as an attribute, as it leads to create a PHP closure, which does not carry the Attribute attribute (sic). It also makes little sense, though the PHP parser accepts it, but not the linter.

Example

<?php

#[Foo(...)]
function goo() {}

?>

Alternatives

  • Remove the three dots from the attribute.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot create Closure for new expression

Description

When using the ... ellpsis operator as an argument, it creates a closure, based on the current function or method. While the syntax can be linted by PHP, it is not possible to use it with a new operator.

Example

<?php

class X {
    function __construct() {}
}

$closure = new X(...);

?>

Alternatives

  • Make a closure that takes the arguments, and relay them to the new operator.
  • Create a named constructor, and make a closure from this.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot create Closure for parent property hook call

Description

parent::$property::get() (and ::set()) is dedicated syntax, resolved at compile time, that invokes the property hook implementation the current class overrides. It does not correspond to a standalone, independently callable method the way parent::method() does, so it cannot be captured as a first-class callable / Closure.

Example

<?php

class Base {
	public string $name = '' {
		get => $this->name;
	}
}

class Child extends Base {
	public string $name = '' {
		get {
			$fn = parent::$name::get(...);
			return $fn();
		}
	}
}

?>

Alternatives

  • Call the parent hook directly instead of turning it into a Closure: parent::$name::get().
  • Wrap the call yourself in an ordinary closure: $fn = fn() => parent::$name::get();

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot create dynamic property %s::$%s

Description

It is not possible to add a property to an enumeration, and it is also not possible to create a property dynamically, on an enumeration object. This is valid for both normal and static properties.

This error message also appears when the class is readonly: then, it is not possible to create any dynamic property.

Example

<?php

enum E: int {
    case Foo = 0;
}

$variable = E::Foo;
$variable->property = 1;

readonly class X {}

$x = new X;
$x->p = 1;

?>

Literal Examples

  • Cannot create dynamic property E::$property

Alternatives

  • Don’t create a property on an enumeration.
  • Don’t create a property on a readonly class.
  • Encapsulate the enumeration in an another class, and set the property on this class.

Cannot create reference to property %s::$%s

Description

While it is possible to acquire a reference on an object’s property, it is not possible to acquire that reference on a property with hooks. By default, the property hook is returned by value, and cannot accomodate the reference. Unless the property hooks is made by reference, with a & before the name of the hook.

The message is also related to using an object in a foreach loop. There is a different message for direct creation of a reference on a property.

Example

<?php

class X {
    public $byRef {
        get {
            $x = 42;
            return $x;
        }
    }
}

foreach (new X as $prop => &$value) {
    var_dump($value);
}

?>

Alternatives

  • Add & before the get hook.
  • Make the property a normal property, without hooks.
  • Avoid using a reference on a property hook.

Cannot declare const %s because

Description

This error is the constant counterpart of the use collision error raised for classes and functions: it fires when a top-level const declaration reuses a name that was already brought into the current file through a use const ... as ... import.

The full message reads: Cannot declare const %s because the name is already in use.

Example

<?php

use const App\FOO as BAR;

const BAR = 42;

?>

Literal Examples

  • Cannot declare const BAR because the name is already in use

Alternatives

  • Rename the const declaration.
  • Change the alias used in the use const import.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot declare hooks for static property

Description

Static properties are not supported for property hooks. Property hooks are only for non-static methods.

Example

<?php

class X
{
    public static string $property {
        set => $this->property . _1;

        SET {
            $this->property = $value;
        }
    }
}
?>

Alternatives

  • Make the property non-static.
  • Create accessors for the static property.

Cannot declare promoted property in an abstract constructor

Description

It is not possible to use a promoted property in an abstract constructor. The promoted property is akin to concrete code (the property assignation), while the abstrat constructor has no body.

On the other hand, a child class may overwrite the constructor signature with a promoted property, so it is possible to define properties that way, but not on an abstract method.

In order to enforce a property, from an abstract class, the property must be defined out of the constructor.

Example

<?php

abstract class X {
	abstract function __construct(private string $a);
}

?>

Alternatives

  • Remove the abstract from the constructor.
  • Define the property outside the construtor.
  • Check all children classes, so they all have the promoted property in their constructor definition.

Cannot declare promoted property outside a constructor

Description

A promoted property is the declaration of a property, as part of the signature of the constructor. It is detected with the use of private, protected and public keyword, in the parameter signature. When these keyword are found in the signature of a method that is not the constructor, PHP emits this error.

Example

<?php

class X {
	function foo(private int $p) {
	
	}
}

?>

Alternatives

  • Remove the private, protected or public keyword.
  • Rename the method __construct, to make it the constructor.
  • Move that parameter to the constructor.

Cannot declare self-referencing constant

Description

A self-referencing constant is a constant that is defined by itself.

This error doesn’t apply to global constants. The global constants are immediately made available, and, for that, they need to be evaluated: this leads to the error Undefined constant A.

Self-referencing constants are not allowed, contraty to self-referencing acronym, that PHP enjoys.

Example

<?php

class X {
    const A = x::A + 1;

    const B = self::C + 1;
    const C = x::B + 1;
}

?>

Alternatives

  • Create a distinct constant that can help build this one.
  • Fix the name of the constant with a distinct one.
  • Fix the name of the class with a distinct one.

Cannot declare variadic promoted property

Description

Properties may be declared, as an parameter in a constructor. Then, they also act as an parameter, and a local variable.

Variadic option is a parameter only option, which pack all the remaning arguments in the final parameter.

Variadic option makes no sense in a property definition, as only one value is stored there.

Example

<?php

class X {
	function __construct(
		private string ...$x
	) {}
}

?>

Alternatives

  • Remove the property definition from the constructor: keep the argument use the variadic, and define the property in the traditional way.
  • Remove the variadic option.

Cannot decrement property %s::$%s of type int past its minimal value

Description

When a property is typed as an int, it cannot have a value lower than PHP_INT_MIN. There is a symetric error with the max value of an integer.

Example

<?php

class X {
    public int $p;
}

$x = new X;

$x->p = PHP_INT_MIN;
--$test->foo;

?>

Literal Examples

  • Cannot decrement property Test::$p of type int past its minimal value

Alternatives

  • Check the value before decrementing.
  • Drop the type, but see the property get turned into a float.

Cannot deserialize ArrayObject with iterator class %s; this class is not derived from ArrayIterator

Description

ArrayObject can be constructed with a custom iterator class (via its second constructor argument), used in place of the default ArrayIterator whenever the object is iterated. That choice is preserved across serialize()/unserialize() by storing the iterator class name as part of the object’s serialized state, and restored inside ArrayObject::__unserialize().

Since that class name travels as a plain string inside the serialized payload, it can end up naming any class, including one with no relation to iteration at all, if the payload was tampered with or was produced by mismatched code. Since PHP 8.6, ArrayObject::__unserialize() requires the named class to actually extend ArrayIterator, and throws an UnexpectedValueException naming the class otherwise, rather than accepting any class that merely implements Iterator.

Example

<?php

$data = 'O:11:"ArrayObject":4:{i:0;i:0;i:1;a:0:{}i:2;a:0:{}i:3;s:8:"stdClass";}';

unserialize($data);

?>

Literal Examples

  • Cannot deserialize ArrayObject with iterator class ‘stdClass’; this class is not derived from ArrayIterator

Alternatives

  • Only unserialize ArrayObject data that was produced by trusted code, and make sure any custom iterator class passed to ArrayObject’s constructor extends ArrayIterator.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, the same UnexpectedValueException was thrown for a class that does not implement Iterator at all, with the message “Cannot deserialize ArrayObject with iterator class ‘%s’; this class does not implement the Iterator interface”. PHP 8.6 tightened the requirement from merely implementing Iterator to actually extending ArrayIterator, and reworded the message to match.](Prior to PHP 8.6, the same UnexpectedValueException was thrown for a class that does not implement Iterator at all, with the message “Cannot deserialize ArrayObject with iterator class ‘%s’; this class does not implement the Iterator interface”. PHP 8.6 tightened the requirement from merely implementing Iterator to actually extending ArrayIterator, and reworded the message to match.)

Cannot directly construct Directory, use dir() instead

Description

Directory is the object returned by the dir() function, giving access to path, handle, read(), rewind() and close(). It predates the rest of PHP’s object model and is a thin, internal wrapper around a directory stream: it has no public constructor of its own.

Calling new Directory(...) directly is rejected, because the object needs to be initialized with an already-opened directory handle, something only dir() can set up correctly.

Example

<?php

$d = new Directory('.');

?>

Alternatives

  • Use dir($path) to obtain a Directory object.
  • Use opendir(), readdir(), closedir() for a purely procedural approach instead of the Directory object.
  • Use DirectoryIterator or RecursiveDirectoryIterator for an object-oriented, iterable interface.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot disable function %s()

Description

The disable_functions (and, for language constructs treated as functions internally, similarly-behaving) php.ini directive lets an administrator remove selected functions from the language, for hardening purposes. A handful of language constructs, namely exit/die and clone, are implemented internally as pseudo-functions so that they can be listed in disable_functions too, but they cannot actually be removed: doing so would leave the engine without a way to terminate a script or clone an object, both of which are needed by the engine itself.

Listing one of these three names in disable_functions does not stop PHP from starting; it only emits this warning once, at startup, and the name stays callable.

Example

; php.ini

disable_functions = exit,die,clone

Literal Examples

  • Cannot disable function exit()
  • Cannot disable function die()
  • Cannot disable function clone()

Alternatives

  • Do not list exit, die or clone in disable_functions; they cannot be disabled.
  • To restrict script termination or cloning, use a different mechanism, such as static analysis, a coding standard, or a runtime policy (open_basedir, custom error/shutdown handlers) instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot increment property %s::$%s of type int past its maximal value

Description

When a property is typed as an int, it cannot have a value higher than PHP_INT_MIN: beyond it, it would be turned into a float. There is a symetric error with the min value of an integer.

Example

<?php

class X {
    public int $p;
}

$x = new X;

$x->p = PHP_INT_MAX;
++$test->foo;

?>

Literal Examples

  • Cannot increment property X::$p of type int past its maximal value

Alternatives

  • Check the value before incrementing.
  • Drop the type, but see the property get turned into a float.

Cannot indirectly modify readonly property %s::$%s

Description

A readonly property cannot be changed after it was set. This includes trying to reach the property via a reference.

Example

<?php

class X {
    readonly public string $property;

    public function __construct() {
        $this->property = 'A';
    }
}

$object = new X;
$variable =& $object->property;

class Y {
    public funciton __construct(
        readonly int &$y
    ) {}
}

?>

Literal Examples

  • Cannot indirectly modify readonly property X::$property

Alternatives

  • Do not create a reference to a readonly property.
  • Do not create a referenced parameter with a promoted property.

Cannot inherit previously-inherited or override constant %s from interface %s

Description

Until PHP 8.1, it was not possible to override a constant when it was defined in an interface, even with the same definition.

Example

<?php

interface I {
    const A = 1;
}

class X implements I {
    const A = 2;
}

?>

Literal Examples

  • Cannot inherit previously-inherited or override constant x from interface i

Alternatives

  • Remove the constant from the class.
  • Remove the constant from the interface.
  • Move to PHP 8.1 or more recent.

Cannot instantiate enum %s

Description

Enumeration cannot be instantiated directly.

An enumeration object is created automatically when reading one of its case.

Example

<?php

enum E {
	case A;
}

//Cannot instantiate enum E
new E();

// E
print get_class(E::A);

?>

Literal Examples

  • Cannot instantiate enum e

Alternatives

  • Use one of the enumeration cases.

Cannot instantiate interface %s

Description

An interface represents an abstract class, and cannot be instantiated alone. For that, the interface must be implemented by a class, aka, it must be specified with the implements keyword.

Example

<?php

interface I {}

//Cannot instantiate interface I
new I();

class XI implements I {
}

new XI(); 

?>

Literal Examples

  • Cannot instantiate interface i

Alternatives

  • Implement the interface with a class and use that class.

Cannot instantiate trait %s

Description

Traits cannot be instantiated directly. They need to be used in a class, or another trait, which will also need to be used in a class.

Example

<?php

trait T {}

//Cannot instantiate trait T
new T();

?>

Literal Examples

  • Cannot instantiate trait t

Alternatives

  • Use one of the class using that trait.
  • Rewrite the trait into an class.

Cannot load module “%s” because required module “%s” is not loaded

Description

This is an error in the structure of the compiled PHP parser. PHP relies on extensions to provide features : xml, sql, http, etc. Sometimes, those extensions are build on top of other extensions: for example, the redis extension requires the json extension.

The names of the modules are displayed in the error messsage: check the installation procedure, as there might be missing extensions or libraries.

Here, modules is another name for a PHP extension.

Example

<?php

// well, the problem might also happen even before
// trying to execute that code

$redis = new Redis();

?>

Literal Examples

  • Cannot load module “redis” because required module “redis” is not loaded

Alternatives

  • Check the module list of PHP, and finish the installation of the missing extension.
  • Remove the first module, which will remove the dependency on the second, and, its related features.

Cannot make non abstract method %s::%s() abstract in class %s

Description

Once a method has a body, it cannot be made abstract again.

On the other hand, the child class may be abstract, while the parent class is not. It just means that new methods must be implemented.

Example

<?php

class X {
    function foo() {}
}

abstract class Y extends X {
    abstract function foo();
}

?>

Alternatives

  • Make the child class the parent.
  • Change the name of the abstract method in the child class.
  • Remove the abstract option in the child class.
  • Add the abstract option in the parent class.
  • Make the method abstract in the parent class.

Cannot make non static method %s::%s() static in class %s

Description

Once a method has been defined, the static keyword, or its absence, must be preserved for the same method in the children classes.

Example

<?php

class X {
    function foo() {}
}

class Y extends X {
    static function foo() {}
}

?>

Literal Examples

  • Cannot make non static method X::foo() static in class Y

Alternatives

  • Add the static keyword to the method in the parent class.
  • Remove the static keyword in all eponymous methods in the children class.
  • Rename some of the methods to avoid a static conflict.

Cannot make static method %s::%s() non static in class %s

Description

Once a method has been defined, the static keyword, or its absence, must be preserved for the same method in the children classes.

Example

<?php

class X {
    function static foo() {}
}

class Y extends X {
    function foo() {}
}

?>

Literal Examples

  • Cannot make static method X::foo() non static in class Y

Alternatives

  • Remove the static keyword to the method in the parent class.
  • Add the static keyword in all eponymous methods in the children class.
  • Rename some of the methods to avoid a static conflict.

Cannot mix [] and list()

Description

list() and the short [] syntax are two different notations for exactly the same destructuring construct. PHP requires a single destructuring expression to use one notation consistently at every nesting level; using list() for the outer pattern and [] for a nested one, or the other way around, is rejected at compile time even though each form is individually valid.

Example

<?php

$data = [1, [2, 3]];

list($a, [$b, $c]) = $data;

?>

Alternatives

  • Use list() consistently at every level: list($a, list($b, $c)) = $data;
  • Use the short [] syntax consistently at every level: [$a, [$b, $c]] = $data;

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot mix bracketed namespace declarations

Description

PHP supports two syntaxes to declare a namespace: the unbracketed form, namespace Foo;, which applies to the rest of the file (or until the next namespace statement), and the bracketed form, namespace Foo { ... }, which delimits the namespace explicitly.

A single file must consistently use one form or the other; mixing bracketed and unbracketed declarations together is not allowed. The full message reads: Cannot mix bracketed namespace declarations with unbracketed namespace declarations.

Example

<?php

namespace A {
    // bracketed syntax
}

namespace B;
// unbracketed syntax, in the same file

?>

Alternatives

  • Convert every namespace statement in the file to the bracketed form.
  • Convert every namespace statement in the file to the unbracketed form.
  • Split the file so that each file only uses one of the two forms.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot mix keyed and unkeyed array entries in assignments

Description

list() is a construct that maps an array to a set of variables. The assignation is done by position, or by key. By position, this means the first value of the array goes to the first variable of the list() : in that case, list() doesn’t specify keys with the => operator. On the other hand, the key are matched by their value, and not their position. The error here happens when list() syntax is created with a mixed set of position and key assignations.

Example

<?php

$array = [];

list(
    '' => $foo,
    $bar
) = $array;
?>

Literal Examples

  • Cannot mix keyed and unkeyed array entries in assignments

Alternatives

  • Remove all the => operators in the list() call.
  • Add all the => operators in the list() call.
  • Make the assignations in a different way.

Cannot modify header information - headers already sent

Description

This error happens when PHP has already started sending the body of the response to the client. In HTTP protocol, the headers must comme first, and after, the body.

There are several reasons for PHP to start sending the body early. Among the most frequent, there might be a space, or the UTF-8 BOM at the beginning of an included file. They may also be at the end of the code, if there is a closing PHP tag.

There may also be some displays, with echo, or from errors.

Example

 <?php
// There is a space before the opening tag

headers('my headers');

// There is a space after the closing tag, which impact including and autoloading files
?> 

Alternatives

  • Check the beginning of the script for invisible, or visible characters before the opening PHP tag.
  • Check the beginning of the UTF-8 BOM before the opening PHP tag.
  • Check the end of the script for invisible characters after the closing PHP tag, if any.
  • Check any included files for the first three tips.
  • Check for any call to a display functions, such as echo, print, print_r, var_dump(), debug_print_backtrace().
  • Check that output_buffering is active in the PHP configuration.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot modify readonly object of class %s

Description

It is possible to call the constructor on an existing object, after its creation. In the case of the Url objects, the underlying URL string is readonly, and the renewed call to the constructor is not possible.

Example

<?php

$uri = new Uri\WhatWg\Url('https://www.php.net/');
$uri->__construct('https://php.net/');

?>

Literal Examples

  • Cannot modify readonly object of class Uri\WhatWg\Url

Alternatives

  • Create a new Url object, instead of updating the existing one.

Cannot modify readonly property %s::$%s

Description

readonly properties can only be set once.

When such property is set in the constructor, there should not be another assignation of this property in another method: it would fail.

When the property is set in another method, then, such method shall only be called once.

They also should be set from their original class (or its children) and not from the public space.

Example

<?php

class X {
	public readonly int $property;
	public int $other;
}

$x = new X;
$x->other = 3;
$x->property = 5;

?>

Literal Examples

  • Cannot modify readonly property x::$property

Alternatives

  • Drop the readonly option.
  • Create an accessor to set the property in the correct context.

Cannot override final %s::%s() with %s::%s()

Description

The final keyword prevents any child class to define the same constant or method. This impacts any class that tries to extends a final class.

Example

<?php

class X {
	final function foo() {}
}

class Y extends X {
	function foo() {}
}

?>

Literal Examples

  • Cannot override final x::foo() with y::foo()

Alternatives

  • Remove the final option in the parent class.
  • Rename the non-final constant or method in the child class.

Cannot override final %s::__construct() with %s::__construct()

Description

The final keyword prevents any child class from redeclaring the same method. Constructors are not exempt from this rule: if a parent class marks its __construct() method as final, no child class may declare its own constructor, even though constructors are otherwise treated differently from regular methods during inheritance checks (their signature is not required to be compatible with the parent’s).

Example

<?php

class X {
    final function __construct() {}
}

class Y extends X {
    function __construct() {}
}

?>

Literal Examples

  • Cannot override final X::__construct() with Y::__construct()

Alternatives

  • Remove the final keyword from the parent constructor.
  • Do not declare a constructor in the child class; it will inherit the parent’s final constructor automatically.
  • Add a differently named factory method in the child class instead of a constructor.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot override final property %s::$%s

Description

A property that is private for writing, is automatically considered final. That is, it cannot be redeclared in a child class, with a different visibility.

Example

<?php

class X {
	public private(set) int $property;
}

class Y extends X {
	public int $property;
}

new Y;

?>

Literal Examples

  • Cannot override final property X::$property

Alternatives

  • Remove the asymmetric visibility from the parent class.
  • Remove the property declaration from the child class.
  • Add the final keyword to the property declaration in the parent (and adapt the children).

Cannot override final property hook %s::%s()

Description

Property hooks may be declared final, just like any other methods. In that case, it is not possible to override then with a new definition in a child class.

The property may be declared final as whole, in the property definition; otherwise, each individual hook may be declared final.

Example

<?php

class X {
	public $property {
		final get => 2;
		set => $this->property = $value;
	}
	// No hook can be changed
	public final $q {
		get => 2;
	}
}

class Y extends X {
	public final $property {
		get => 3;                 // This one cannot be overriden
		set => $this->property = $value; // This one is OK
	}
	public final $q {
		get => 2;
	}
}

?>

Literal Examples

  • Cannot override final property hook $p::get()

Alternatives

  • Remove the final keyword on the parent hook.
  • Remove the hook in the child class.

Cannot pass parameter %d by reference

Description

When a parameter is set to be passed by reference, there is a & character before its name. In that case, the argument must be a data container, such as a variable, a property, a static property, an array index, but it cannot be a literal value, a constant, or the result of an expression.

Example

<?php

function foo(&$a) {}

// invalid cases
foo(1);
foo(1 + 2);

const A = 1;
foo(A);

class X {
    const B = 2;
}
foo(X::B);

?>

Literal Examples

  • Cannot pass parameter 1 by reference

Alternatives

  • Store the value in a variable and passe the variable.
  • Remove the reference in the method signature.

In more recent PHP versions, this error message is now :ref:%s():-argument-#%d%s%s%s-cannot-be-passed-by-reference.

Cannot perform bitwise not on %s

Description

Bitwise operations are only available on integers. Other types are forbidden. Among the operations ~ is a bitwise operation. For the other operators, a different error is emitted.

Example

<?php

$array = [1,2];

~$array;

?>

Literal Examples

  • Cannot perform bitwise not on object
  • Cannot perform bitwise not on boolean
  • Cannot perform bitwise not on resource
  • Cannot perform bitwise not on array

Alternatives

  • Use another operator than the bitwise not, such as !.
  • Cast the forbidden type to int before using the bitwise.

Cannot re-assign $this

Description

It is never possible to assign a new value to the pseudo-variable $this, inside a class or outside. In fact, it is also never allowed to unset it either. In short, it is possible to read $this, and nothing more.

Example

<?php

unset($this);

?>

Alternatives

  • Remove this call to unset.

Cannot re-assign auto-global variable %s

Description

It is not possible to use one of the superglobal variable names as argument of a method: such code hides the assignation that happens at call time, which will interfere with the $_POST variable being a global. Hence, such syntax is forbidden.

The error is not emitted when the same superglobal variables are used as variables, as it may be legit code.

This applies to all PHP superglobal, such as $_ENV, $GLOBALS, or $_POST. See the full list in annex.

Example

<?php

function foo($_POST) {

}

?>

Literal Examples

  • Cannot re-assign auto-global variable $_POST

Alternatives

  • Use a parameter anme that is not a superglobal or a special PHP variable.

Cannot rebind scope of closure created from function, this will be an error in PHP 9

Description

A closure created from a plain, top-level function (Closure::fromCallable('foo') or foo(...)) has no class scope: it was never attached to an object or a class in the first place. Passing a scope argument to Closure::bind() or Closure::bindTo() on such a closure has nothing to rebind.

Since PHP 8.5, this operation already emitted an E_WARNING and the bind silently failed, returning null. It is now deprecated and will become a fatal error in PHP 9.0.

Example

<?php

class X {}

function foo() {
    return __FUNCTION__;
}

$fn = Closure::fromCallable('foo');
$fn2 = Closure::bind($fn, new X, X::class);
var_dump($fn2);

?>

Literal Examples

  • Cannot rebind scope of closure created from function, this will be an error in PHP 9

Alternatives

  • Do not attempt to bind a scope to a closure created from a plain function; it has none.
  • If scoped behaviour is required, define the closure inside the class (as a method or a property initializer) instead of wrapping a free function.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See closure

Cannot rebind scope of closure created from method, this will be an error in PHP 9

Description

When a closure is created from an object method ($obj->method(...)), its scope and binding are tied to the originating object. Attempting to rebind that closure to a different scope or object using Closure::bind() or Closure::bindTo() is not allowed.

In PHP 7.0, this was silently accepted. Since PHP 8.0, it raises a warning. In PHP 9.0, it will be a fatal error.

The restriction exists because a method-bound closure captures the object’s internal context. Rebinding it would violate encapsulation by granting access to private and protected members of an unrelated class.

Example

<?php

class X {
    public function method() {}
}

class Y {}

$x = new X;
$fn = $x->method(...);
$fn->bindTo($x, Y::class);

?>

Literal Examples

  • Cannot rebind scope of closure created from method, this will be an error in PHP 9

Alternatives

  • Create the closure from within the class itself using [self, 'method'] or Closure::fromCallable() to allow rebinding.
  • Avoid rebinding method-bound closures; use call_user_func() or $closure(...) with the original binding.
  • If you need a rebound closure, create a standalone closure that wraps the method call.

In previous PHP versions, this error message used to be :ref:cannot-rebind-scope-of-closure-created-from-method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot rebind scope of closure created from method

Description

When a closure is build from a method and an existing object, it is not possible to rebind it to another object.

Example

<?php

class X {
    function method () {}
}

class Y {}

$x = new X;
$fn = $x->method(...);
$ret = $fn->bindTo($x, Y::class);

?>

Alternatives

  • To be rebound, the closure must be build from within the class.

In more recent PHP versions, this error message is now :ref:cannot-rebind-scope-of-closure-created-from-method,-this-will-be-an-error-in-php-9.

Cannot redeclare %s%s::$%s as %s%s::$%s

Description

A non-private property redeclared in a child class must keep the same static/non-static nature as in the parent class. A static property belongs to the class itself, while a non-static property belongs to each instance; the two are fundamentally different storage locations, so a child class cannot silently turn one into the other while inheriting from the same family.

Here, X::$property is declared static, and Y redeclares it as an instance property, which is rejected.

This is a distinct check from the one that reports readonly conflicts between parent and child properties: that message uses the literal word “property” (as in Cannot redeclare readonly property X::$property as non-readonly Y::$property), while the static/non-static check never does.

Example

<?php

class X {
    protected static $property;
}

class Y extends X {
    protected $property;
}

?>

Literal Examples

  • Cannot redeclare static X::$property as non static Y::$property
  • Cannot redeclare non static X::$property as static Y::$property

Alternatives

  • Make both declarations static.
  • Make both declarations non-static.
  • Remove the redeclaration in the child class, and inherit the parent property as-is.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare %s() (previously declared in %s:%d)

Description

Functions must have a unique name: there cannot be two functions with the same name.

Function names are case insensitive, so making changing the case doesn’t make the function name unique.

In fact, two functions in the same namespace cannot have the same name, so the complete constraint is namespace + function must be unique.

Example

<?php

function foo() {}

function FOO() {}

?>

Literal Examples

  • Cannot redeclare foo() (previously declared in file:3)

Alternatives

  • Change the name of the function.
  • Make the function a closure.
  • Move the function to another namespace.

In more recent PHP versions, this error message is now :ref:cannot-redeclare-function-%s()-(previously-declared-in-%s:%d).

Cannot redeclare %s %s (previously declared in %s:%d)

Description

A class, interface, trait or enum name can only be declared once per request, whether that happens directly in the same file or because two different, user-defined files both declare the same name. This is the general form of the redeclaration error: the first placeholder is the kind of symbol (class, interface, trait or enum), the second is its name, and the location points at the file and line of the earlier, conflicting declaration.

Unlike functions, none of these can be conditionally redeclared, even if the two declarations are byte-for-byte identical.

Example

<?php

interface Foo {
}

interface Foo {
}

?>

Literal Examples

  • Cannot redeclare interface Foo (previously declared in /path/to/file.php:3)
  • Cannot redeclare trait Foo (previously declared in /path/to/file.php:3)
  • Cannot redeclare enum Foo (previously declared in /path/to/file.php:3)

Alternatives

  • Use include_once or require_once instead of include or require to avoid loading the same file twice.
  • Wrap the declaration in a class_exists()/interface_exists()/trait_exists()/enum_exists() check if it may legitimately be loaded more than once.
  • Rename one of the two symbols, or move them into different namespaces.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare %s %s

Description

This is the general form of the class/interface/trait/enum redeclaration error, used specifically when the conflicting name is already taken by an internal symbol, one built into PHP itself or provided by a loaded extension, rather than by another user-defined file. Because internal classes and interfaces have no PHP source file or line number of their own, the message omits the (previously declared in ...) location that appears when the conflict is with another user-defined file.

The first placeholder is the kind of symbol (class, interface, trait or enum), the second is its name.

Example

<?php

interface Stringable {
}

?>

Literal Examples

  • Cannot redeclare interface Stringable
  • Cannot redeclare class stdClass

Alternatives

  • Rename the declaration to avoid colliding with a built-in or extension-provided name.
  • Wrap the declaration in a class_exists()/interface_exists()/trait_exists()/enum_exists() check, though this rarely helps for internal symbols since they are always present.

In more recent PHP versions, this error message is now :ref:cannot-redeclare-%s-%s-(previously-declared-in-%s:%d).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare %s property %s::$%s as %s %s::$%s

Description

A property must be always readonly or non-readonly, in every classes of the same family. It cannot alternate between the two options, with inheritance.

The same applies also to the static option of properties.

Example

<?php

class X {
    private readonly $property;
}

class Y extends X {
    private $property;
}

?>

Literal Examples

  • Cannot redeclare readonly property X::$property as non-readonly Y::$property
  • Cannot redeclare non-readonly property X::$property as readonly Y::$property
  • Cannot redeclare static property X::$property as non-static Y::$property
  • Cannot redeclare non-static property X::$property as static Y::$property

Alternatives

  • Make all the property definitions readonly.
  • Make all the property definitions non-readonly.
  • Remove some the conflicting property definitions.

Cannot redeclare %s::$%s

Description

A property can only be declared once in a class. This error appears when the same property name is declared twice in the same class body, regardless of whether the visibility or default value differ between the two declarations.

The same restriction applies to promoted properties: a constructor parameter promoted to a property cannot share its name with a property already declared in the class body.

Example

<?php

class X {
    public $a;
    public $a;
}

?>

Literal Examples

  • Cannot redeclare X::$a

Alternatives

  • Remove one of the two duplicate property declarations.
  • Rename one of the two properties.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare %s::%s()

Description

Each method in a class must have a distinct name. There can be not two methods with the same name.

The parent classes, or the traits, may have duplicate methods: these will be ignored.

One special case are the enumeration: the backed enumeration, with their type, import two methods to convert a value into one of the case: try and tryFrom. Then, these two methods are part of the definition of the enumeration, and it is not possible anymore to define them in the enumeration.

Example

<?php

class X {
    function foo() {}
    function foo() {}
}

enum E {
    function try() {}
    function tryFrom() {}
}

?>

Literal Examples

  • Cannot redeclare X::foo()
  • Cannot redeclare X::try()
  • Cannot redeclare X::tryFrom()

Alternatives

  • Remove one of the duplicate function.
  • Rename one of the duplicate function.

Cannot redeclare class %s

Description

A class name can only be declared once per request. This error appears when the same class name is declared twice, either directly in the same file, or because a file defining the class was included more than once (for instance with include instead of include_once), or because two different files both declare a class with the same name.

Unlike functions, PHP does not allow a class to be conditionally redeclared, even if the two declarations are identical.

Example

<?php

class X
{
}

class X
{
}

?>

Literal Examples

  • Cannot redeclare class X

Alternatives

  • Use include_once or require_once instead of include or require to avoid loading the same file twice.
  • Wrap the class declaration in a class_exists() check if it may legitimately be loaded more than once.
  • Rename one of the two classes, or move them into different namespaces.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare constant ‘%s’

Description

A constant declared at the top level with the const keyword can only be declared once per namespace, per request. This is a compile-time error, unlike the runtime warning produced when calling define() twice with the same constant name.

This error also happens when a file declaring a top-level constant is included more than once without a guard.

Example

<?php

const FOO = 1;
const FOO = 2;

?>

Literal Examples

  • Cannot redeclare constant ‘FOO’

Alternatives

  • Remove the duplicate const declaration.
  • Use include_once or require_once for files that declare top-level constants.
  • If the constant needs to be conditionally declared, use define() together with defined() instead of const.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare function %s() (previously declared as local import)

Description

A use function statement imports a function under a local name, in the current namespace. When a function is then declared, in the same namespace, under that same local name, and its declared name differs (case insensitively) from the fully qualified imported name, PHP cannot tell which of the import or the local declaration should be used.

This is detected at compile time, as soon as the local function declaration is compiled.

Example

<?php

namespace App;

use function Other\bar;

function bar() {}

?>

Literal Examples

  • Cannot redeclare function bar() (previously declared as local import)

Alternatives

  • Remove the use function import, and call the function using its fully qualified name.
  • Alias the import with the as keyword, so it no longer collides with the local function name.
  • Rename the local function.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare function %s() (previously declared in %s:%d)

Description

Functions must have a unique name: there cannot be two functions with the same name.

Function names are case insensitive, so making changing the case doesn’t make the function name unique.

In fact, two functions in the same namespace cannot have the same name, so the complete constraint is namespace + function must be unique.

Example

<?php

function foo() {}

function FOO() {}

?>

Literal Examples

  • Cannot redeclare foo() (previously declared in file:3)

Alternatives

  • Change the name of the function.
  • Make the function a closure.
  • Move the function to another namespace.

In previous PHP versions, this error message used to be :ref:cannot-redeclare-%s()-(previously-declared-in-%s:%d).

Cannot redeclare function %s()

Description

This variant of the function redeclaration error is raised by OPcache, when it merges a script’s freshly compiled functions into its shared-memory function table and finds a name collision with a function that is already cached, but for which OPcache has no usable source location (for example, a function generated at runtime, or one whose original op_array metadata is otherwise unavailable). Because there is nothing meaningful to point at, the message omits the (previously declared in ...) part that the ordinary redeclaration error includes.

Functionally, this is the same constraint as the plain function redeclaration error: two functions cannot share the same name (case-insensitively) within the same namespace.

Example

<?php
// requires the Zend OPcache extension to be enabled

function foo() {}

?>

Literal Examples

  • Cannot redeclare function foo()

Alternatives

  • Change the name of one of the two functions.
  • Guard the declaration with function_exists() if the file may legitimately be included more than once.
  • Use include_once or require_once instead of include or require.

In previous PHP versions, this error message used to be :ref:cannot-redeclare-function-%s()-(previously-declared-in-%s:%d).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare property hook “%s

Description

Property hook may only have one definition. It is not possible to have duplicates.

Example

<?php

class Test {
    public $prop {
        GeT {}
        get {}
        
    }
}

?>

Literal Examples

  • Cannot redeclare property hook “get”

Alternatives

  • Remove all but one of the definition.
  • Rename one of them with the other property hook name: may be set had a typo and was written get.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redeclare property hook

Description

Property hooks must be all distinct, and there can only be two. In that case, it is get and set. Property hooks are case insensitive, so get and GET are the same.

They also differ one from the other by one letter, so review is important.

Example

<?php

class X
{
    public string $property {
        set => $this->property . _1;

        SET {
            $this->property = $value;
        }
    }
}
?>

Alternatives

  • Make sure that both hooks are needed.
  • Remove any third hook: there can only be two, at most.
  • Check case of the hooks name.

Cannot redefine class constant %s::%s

Description

PHP does not allow the same constant twice in the same class. The constant may be declared several times in different classes, including extending or extended ones, or in trait, as each case has conflict resolution mechanisms.

Example

<?php

class C {
    const FOO = hello;
    const FOO = hello again;
}

?>

Literal Examples

  • Cannot redefine class constant C::FOO

Alternatives

  • Rename one of the conflicting constants.
  • Remove one of the conflicting constants.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot redefine class constant

Description

It is only allowed to defined a constant once per class.

A constant with the same name may be defined in a parent or child class, or even in a trait: there are rules that allow PHP to select one of them, whenever there is a possible name conflict.

At the class, interface, trait level, the constants must all be distinct.

At the enumeration level, the naming conflict may arise between a case and a const: the error message is then the same.

This error applies to class constants, and there is a different error for global constants.

Example

<?php

class X {
	const A = 1, A = 1;
}

enum E {
	case B;

	const B = 1;
}

?>

Alternatives

  • Remove one of the constant.
  • Rename one of the constant.
  • Move one of the constant to a parent, trait or interface.

Cannot rewind a generator that was already run

Description

In this code, $g includes the generator, and it is run twice, from the first loop in $h, and then, in the second loop with $i.

Example

<?php

$g = function (): Generator {
    yield from [1,2,3,4];
};    echo $i +;

$g = $g();

foreach($g as $h) {
    print h:$h -;
    foreach($g as $i) {
        echo i:$i +;
        
        break 1;
    }
}

?>

Alternatives

  • Do not reuse the generator in two loops, but rather call $g() each time. It generates distinct and new data sources.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot set a userinfo without having a host

Description

Per RFC 3986, the userinfo component (user:pass@) only exists as part of an authority, and an authority always includes a host. There is no valid way to serialize a URI that carries userinfo but no host. Uri\Rfc3986\UriBuilder::build() (and the equivalent withUserInfo() call on an already-hostless URI) rejects that combination instead of producing a URI that would be ambiguous or unparsable when read back.

Example

<?php

$builder = new Uri\Rfc3986\UriBuilder();
$builder->setUserInfo('user:pass');

$uri = $builder->build();

?>

Alternatives

  • Set a host on the builder (or the URI) before, or at the same time as, setting the userinfo.
  • If the URI genuinely has no authority (e.g. a mailto: URI), do not set userinfo on it.

In more recent PHP versions, this error message is now :ref:the-specified-userinfo-is-malformed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot specify default value for virtual hooked property

Description

It is possible to create a virtual property, by defining one accessor that doesn’t refer to the defined property. In the illustration here, the get method is empty. In that case, the property’s value doesn’t have an impact on the operation, and the default value of that property shall not be defined.

Example

<?php

class X {
	public int $property = 3 {
		get {}
	}
}

?>

Alternatives

  • Remove the property hooks, to regain usage of the default value.
  • Define a property hook that makes use of the property $this->property.

Cannot take reference of a nullsafe chain

Description

The nullsafe operator ?-> short-circuits the whole access chain to null as soon as one segment is null: the rest of the chain is never evaluated. A reference, on the other hand, must point to a concrete storage location (a variable, array slot, or property); there is no such location to bind to when the chain may short-circuit to a plain null value instead.

This error is raised whenever ANY segment of a chain used in a by-reference context contains a nullsafe operator, whether the reference is taken with &, passed to a by-reference function or method parameter, or used in a by-reference foreach. It is a compile-time error, detected regardless of whether the chain would actually short-circuit at runtime.

Example

<?php

class Address {
    public string $city = '';
}

class User {
    public ?Address $address = null;
}

$user = new User();

$city = &$user?->address->city;

?>

Alternatives

  • Use the regular -> operator instead of ?->, after making sure the intermediate value cannot be null.
  • Split the expression: check for null first, then take the reference with ->.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot throw objects that do not implement Throwable

Description

All classes that are thrown must implement the interfave Throwable. It is possible to catch Throwable objects, but in fact, it is not possible to implement Throwable in a class: this is done by extending either Exception or Error, which, in turn, implements Throwable.

Example

<?php

class X {}

throw new X();

?>

Alternatives

  • Make the class extends \Exception.
  • Make the class extends \Error.
  • Do not throw the class.

Cannot unbind $this of closure using $this, this will be an error in PHP 9

Description

A closure literal that references $this in its body captures the enclosing object when it is created. Rebinding it to null with bindTo() or Closure::bind() would leave the body referencing $this with nothing bound to it, so the operation is refused.

A closure that does not use $this in its body can still be unbound safely; the restriction only applies when $this is actually referenced.

Since PHP 8.5, this operation already emitted an E_WARNING and the bind silently failed, returning null. It is now deprecated and will become a fatal error in PHP 9.0.

Example

<?php

class X {
    public $prop = 'hello';

    public function getClosure() {
        return function () {
            return $this->prop;
        };
    }
}

$x = new X;
$fn = $x->getClosure();
$fn2 = $fn->bindTo(null);
var_dump($fn2);

?>

Literal Examples

  • Cannot unbind $this of closure using $this, this will be an error in PHP 9

Alternatives

  • If the closure needs to run without an object context, remove every use of $this from its body.
  • Keep the closure bound to the object and pass the values it needs as parameters instead of relying on unbinding.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See closure

Cannot unbind $this of method, this will be an error in PHP 9

Description

A closure created directly from a non-static method ($obj->method(...) or ReflectionMethod::getClosure()) is a $this-call in disguise: the method body may use $this freely, whether or not it is written explicitly. Since PHP 8.0 removed static calls to non-static methods, $this is guaranteed to exist whenever such a method runs, so bindTo(null) can no longer strip it.

Since PHP 8.5, this operation already emitted an E_WARNING and the bind silently failed, returning null. It is now deprecated and will become a fatal error in PHP 9.0.

Example

<?php

class X {
    public function method() {
        return __METHOD__;
    }
}

$x = new X;
$fn = $x->method(...);
$fn2 = $fn->bindTo(null);
var_dump($fn2);

?>

Literal Examples

  • Cannot unbind $this of method, this will be an error in PHP 9

Alternatives

  • Keep the closure bound to the object; call it with the original binding instead of unbinding $this.
  • If a scope-free version of the logic is needed, extract it into a standalone function that does not rely on the method’s $this.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See closure

Cannot unpack array with string keys

Description

Initialy, the ellipsis operator would only work with integer-indexed arrays, and not with string-indexed arrays. This feature was introduced in PHP 8.1, and the error message then disappeared.

Example

<?php

$array = ['a' => 1, 2];
$array2 = [...$array, 3];

?>

Alternatives

  • Upgrade the code to PHP 8.1 or newer.
  • Use array_keys() before using the ellipsis operator.

Cannot unset $this

Description

It is never possible to unset the pseudo-variable $this, inside a class or outside. Actually, it is also never allowed to write to it. In short, it is possible to read $this, and nothing more.

Example

<?php

unset($this);

?>

Alternatives

  • Remove this call to unset.

Cannot unset hooked property %s::$%s

Description

It is not allowed to unset a hooked property, aka, a property with a get or set (or both) hook.

Example

<?php

class X {
    public string $property {
        get => $this->x;
    }
}

$x = new X;
unset($x->x);

?>

Literal Examples

  • Cannot unset hooked property x::$property

Alternatives

  • Assign null, or a null value to this property.
  • Reset the property to its default value.

Cannot unset offset in a non-array variable

Description

The array syntax $variable[index] is only available for arrays and strings. When used on other types, PHP emits a fatal error.

The boolean false and the null value still accept this behavior. The first is deprecated in PHP 8.1, and the second valid in PHP 8.3.

Example

<?php

$x = true;
$x[0] = 1;

?>

Alternatives

  • Check for type before using the array syntax.
  • Keep using consistent types with each variables.
  • Set type with properties to ensure they are consistent.
  • Cast the object to array before usage.

In previous PHP versions, this error message used to be :ref:cannot-use-object-of-type-stdclass-as-array.

Cannot unset readonly property %s::$%s

Description

Once a readonly property has been set, it cannot be unset. That would defeat the whoe purpose of readonly.

Example

<?php

class X {
    public readonly $property;
    
    function __construct($a) {
        $this->property = $a;
        unset($this->property);
    }
}

?>

Literal Examples

  • Cannot unset readonly property X::$property

Alternatives

  • Use clone to create a new object, and have a chance to change that value.
  • Remove the unset call.
  • Remove the readonly property.

Cannot unset string offsets

Description

While strings and arrays share the same syntax with square brackets, to access individual elements, that syntax is not available with the unset() function. Strings do not behave like an array, so it is not possible to remove one char with unset.

Example

<?php

$a = 'abc';
unset($a);

?>

Alternatives

  • Explode() the string into an array, use the unset() on the array, and then, implode() it back into a string.
  • Use substr() twice, to cut out the unwanted character.
  • Use preg_replace(), to replace the character with an empty string.
  • Use strtr(), to replace the character with an empty string, if it is unique.

Cannot use%s %s as %s because the name is already in use

Description

This error appears when a name, for class, interface, trait or enumeration was already used by a use command. This is usually a problem within the block that has the use.

Example

<?php

use X as Y;

class Y {}

?>

Literal Examples

  • Cannot use X as Y because the name is already in use

Alternatives

  • Use another name for the alias.
  • Use another name for the definition.

Cannot use(…) variables in constant expression

Description

It is possible to have closures in a constant, since PHP 8.5. Such closure must be static, so that it does not include the current object with $this. It also cannot use the use clause, as the definition of the closure is outside an execution context: there are no available variables to import in the closure.

Example

<?php

class X {
    const MY = static function () use ($a) { return 1;};
}

?>

Alternatives

  • Remove the use clause of the closure.
  • Move the closure inside a method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use “%s” as a type name as it is reserved

Description

array is a native PHP type, and it cannot be used with the leading \. This is also the case for the other native types, such as int or string, although they provide a different error message.

Example

<?php

function foo(\array $array) {}

?>

Literal Examples

  • Cannot use “array” as a type name as it is reserved

Alternatives

  • Remove the leading \, before the array.
  • Change the type from array to an actual class.

Cannot use “%s” when no class scope is active

Description

self, static and parent refers to the classes, relative to the current one. As such, they can only be used inside a class or a trait.

Example

<?php

static::x;

?>

Literal Examples

  • Cannot use “static::” when no class scope is active
  • Cannot use “static” when no class scope is active

Alternatives

  • Move the code inside a method, in a trait or a class.
  • Use the full name of the class that should be used.

Cannot use “abstract” as method modifier in trait alias

Description

When resolving name conflicts during trait imports, it is not possible to use abstract with the as keyword. The situation is actually confusing: abstract may be the name of the alias, or it could also be understood as the modifier.

The same situation arise with abstract, final or readonly. On the other hand, it is valid to use the visibility modifier to actually change the visibility on the alias.

This message was completed with ‘in trait alias’, in PHP 8.2.

Example

<?php
trait T1 {
	function foo() {}
}
class C1 {
	use T1 {
		T1::foo as abstract;
	}
}
?>

Alternatives

  • Use another name than abstract for the alias.
  • Use another name than abstract for the original method.

In previous PHP versions, this error message used to be :ref:cannot-use-'abstract'-as-method-modifier.

Cannot use “parent” when current class scope has no parent

Description

parent keyword represents the first available class in the current class hierarchy. A class has a parent class, when that class uses the extends keyword. When the current class has no such keyword, it has no parent and cannot use it.

This error applies to parent as a class descriptor or as a type.

Example

<?php

class X {
    function foo(parent $y) {
        parent::goo();
    }
}

?>

Alternatives

  • Add a parent to the current class.
  • Use another class name, instead of parent: for example, the actual name of the target class, rather than the relative one.

In previous PHP versions, this error message used to be :ref:parameter-uses-'parent'-as-type-hint-although-class-does-not-have-a-parent!.

Cannot use “parent” when no class scope is active

Description

parent is a keyword that represent the parent class of the current class. When the code is not located inside a class, it cannot have a parent, and so, is forbidden.

Example

<?php

function foo(parent $argument) { }

?>

Alternatives

  • Convert the function into a method, in a class with a parent.
  • Convert the function into a closure, and assign it a to an object of a class with a parent.

Cannot use “static” when no class scope is active

Description

static refers to the class that was called to access the class elements (constants, method, properties..). As such, static can only be used inside a class or a trait.

Example

<?php

static::x;

?>

Alternatives

  • Move the code inside a method, in a trait or a class.
  • Use the full name of the class that should be used.

In previous PHP versions, this error message used to be :ref:cannot-access-static::-when-no-class-scope-is-active.

Cannot use $this as global variable

Description

The pseudo-variable $this is automatically available inside every method of a class, and refers to the current object. It is not possible to import $this into the global symbol table using the global keyword. $this is special and not a regular variable that may be made global.

Example

<?php

class X {
    function foo() {
        global $this;
    }
}

(new X)->foo();

?>

Alternatives

  • Use $this directly inside the method, without importing it as global.
  • Pass the object as a parameter to the function that needs it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use $this as lexical variable

Description

A lexical variable is a variable imported into a closure via the use clause. Since PHP 8.1, $this is automatically available inside all closures defined in an object context, so it is no longer allowed to explicitly import it as a lexical variable. This is also true for arrow functions, which implicitly capture $this when defined inside a method.

Example

<?php

class X {
    function foo() {
        $fn = function () use ($this) {
            return $this;
        };
    }
}

(new X)->foo();

?>

Alternatives

  • Remove $this from the use clause, since it is automatically available in the closure.
  • Use a static closure if $this is not needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use $this as parameter

Description

Cannot use $this as parameter. Using $this as a method parameter is not allowed in PHP.

Example

<?php

    function foo($this) { }

?>

Alternatives

  • Pass the object as a parameter by creating a method that accepts an object parameter instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use $this as static variable

Description

$this is a special variable, automatically bound to the current object inside a method. It cannot be redefined, in particular by making it a static variable, which would give it a persistent value between calls and remove its automatic binding to the object.

This is checked at compile time, whether the method is ever called or not.

Example

<?php

class X {
    public function foo() {
        static $this;
    }
}

?>

Alternatives

  • Use another variable name for the static variable.
  • Store the required data in a property of the object instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use %s() on dynamic property %pS::$%pS

Description

ReflectionProperty::setRawValueWithoutLazyInitialization() and ::skipLazyInitialization() are part of the lazy objects API (PHP 8.4): they work by reaching directly into the storage slot reserved for a declared property, bypassing the object’s lazy initializer. A dynamic property (one added to a specific object at runtime rather than declared in its class) has no such reserved slot, so these methods have nothing to operate on and throw instead.

Since ReflectionProperty is constructed from a property name that may or may not correspond to an actual declared property on the given object, this can only be detected at call time, once the object is known.

Example

<?php

class Foo {}

$obj = new Foo();
$obj->bar = 1;

$prop = new ReflectionProperty($obj, 'bar');
$prop->setRawValueWithoutLazyInitialization($obj, 2);

?>

Literal Examples

  • Cannot use setRawValueWithoutLazyInitialization() on dynamic property Foo::$bar
  • Cannot use skipLazyInitialization() on dynamic property Foo::$bar

Alternatives

  • Only call setRawValueWithoutLazyInitialization()/skipLazyInitialization() for properties that are actually declared on the object’s class, e.g. after checking ReflectionProperty::isDynamic() (or checking the object with property_exists() against the class declaration).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on dynamic property %s::$%s” (no parentheses after the method name, and “Can not” as two words).](Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on dynamic property %s::$%s” (no parentheses after the method name, and “Can not” as two words).)

Cannot use %s() on internal class %pS

Description

ReflectionProperty::setRawValueWithoutLazyInitialization() and ::skipLazyInitialization() are part of the lazy objects API (PHP 8.4). Making an object lazy relies on the engine’s default property read/write handlers, so it can intercept property access to trigger initialization. Some internal (C-implemented) classes, such as ZipArchive, install their own custom property handlers instead and cannot be made lazy, so a declared property found on such a class still cannot be manipulated through these low-level, lazy-initialization-only APIs, and PHP throws instead of writing to a slot that the object’s own handlers do not expect to be touched directly.

Example

<?php

$zip = new ZipArchive();

$prop = new ReflectionProperty($zip, 'status');
$prop->setRawValueWithoutLazyInitialization($zip, 0);

?>

Literal Examples

  • Cannot use setRawValueWithoutLazyInitialization() on internal class ZipArchive
  • Cannot use skipLazyInitialization() on internal class ZipArchive

Alternatives

  • Use ReflectionProperty::setValue() to set a property on an internal class instance, since setRawValueWithoutLazyInitialization()/skipLazyInitialization() only work with classes that support the engine’s default property handlers and can be made lazy.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on internal class %s” (no parentheses after the method name, and “Can not” as two words).](Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on internal class %s” (no parentheses after the method name, and “Can not” as two words).)

Cannot use %s() on static property %pS::$%pS

Description

ReflectionProperty::setRawValueWithoutLazyInitialization() and ::skipLazyInitialization() are part of the lazy objects API (PHP 8.4): they exist to manipulate the storage slot of a lazily-initialized instance property without triggering (or interfering with) the object’s lazy initializer. A static property belongs to the class, not to any particular instance, and is never subject to per-object lazy initialization, so these methods refuse to act on it.

Example

<?php

class Foo {
    public static int $counter = 0;
}

$obj = new Foo();

$prop = new ReflectionProperty(Foo::class, 'counter');
$prop->setRawValueWithoutLazyInitialization($obj, 5);

?>

Literal Examples

  • Cannot use setRawValueWithoutLazyInitialization() on static property Foo::$counter
  • Cannot use skipLazyInitialization() on static property Foo::$counter

Alternatives

  • Use ReflectionProperty::setValue() for static properties instead of setRawValueWithoutLazyInitialization()/skipLazyInitialization(), which only make sense for lazily-initialized instance properties.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on static property %s::$%s” (no parentheses after the method name, and “Can not” as two words).](Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on static property %s::$%s” (no parentheses after the method name, and “Can not” as two words).)

Cannot use %s() on virtual property %pS::$%pS

Description

ReflectionProperty::setRawValueWithoutLazyInitialization() and ::skipLazyInitialization() are part of the lazy objects API (PHP 8.4): they reach directly into the memory slot backing an ordinary, storage-based property, bypassing the object’s lazy initializer. A virtual property (a property hook declared with only get/set and no backing $this->propName storage, from PHP 8.4’s property hooks feature) has no such slot at all, so these methods have nothing to write to and throw instead.

Example

<?php

class Foo {
    public int $bar {
        get => 5;
    }
}

$obj = new Foo();

$prop = new ReflectionProperty($obj, 'bar');
$prop->setRawValueWithoutLazyInitialization($obj, 2);

?>

Literal Examples

  • Cannot use setRawValueWithoutLazyInitialization() on virtual property Foo::$bar
  • Cannot use skipLazyInitialization() on virtual property Foo::$bar

Alternatives

  • Only call setRawValueWithoutLazyInitialization()/skipLazyInitialization() on properties that actually have backing storage, i.e. hooked properties that reference $this->propName in their get/set hooks, not purely virtual ones.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on virtual property %s::$%s” (no parentheses after the method name, and “Can not” as two words).](Prior to PHP 8.6, the same ReflectionException was thrown, but worded “Can not use %s on virtual property %s::$%s” (no parentheses after the method name, and “Can not” as two words).)

Cannot use %s as %s because %s is a special class name

Description

Some words, such as float, never, _, … are reserved by PHP and cannot be used as an alias name, just like they are not allowed with class names.

Example

<?php

use X as string;

?>

Literal Examples

  • Cannot use X as string because string is a special class name

Alternatives

  • Use another name.

Cannot use %s as array

Description

This error is emitted when the right operand of a list operation is not an array, but a scalar, with the exception of null.

Example

<?php

list($a, $b) = 'abc';

?>

Literal Examples

  • Cannot use string as array
  • Cannot use boolean as array
  • Cannot use integer as array
  • Cannot use float as array
  • Cannot use object as array

Alternatives

  • Convert the right operand to an array first.
  • Use a simple assignation, rather than list.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See destructuringNonArray

Cannot use %s as default value for parameter $%s of type %s

Description

The default value of the parameter is not compatible with the type of the parameter. In the example here, the parameter $s is an integer, but has a string as default value.

This error also applies to numeric strings: the default value must be of the same type, without any silent type juggling.

It used to be recommended to make the default value NULL as it would be implicitely accepted by the type. Yet, in PHP 8.4, this is now a deprecated behavior, and it is not recommended anymore.

Example

<?php

function foo(int $s = 's') { }

function bar(int $s = '1') { }

?>

Literal Examples

  • Cannot use 3 as default value for parameter $a of type array

Alternatives

  • Change the type of the parameter.
  • Change the default value.
  • Remove the default value.
  • Remove the type value.
  • Add a second union type to the parameter.

In previous PHP versions, this error message used to be :ref:default-value-for-parameters-with-a-%s-type-can-only-be-%s-or-null.

Cannot use %s as default value for property %s::$%s of type %s

Description

The default value of the property is not compatible with the type of the same property. In the example here, the property $s is an integer, but has a string as default value.

This error also applies to numeric strings: the default value must be of the same type, without any silent type juggling.

It used to be recommended to make the default value NULL as it would be implicitely accepted by the type. Yet, in PHP 8.4, this is now a deprecated behavior, and it is not recommended anymore.

Example

<?php

class X {
    public string $property = 3;
}

?>

Literal Examples

  • Cannot use 3 as default value for property X::$property of type string

Alternatives

  • Change the type of the parameter.
  • Change the default value.
  • Remove the default value.
  • Remove the type value.
  • Add a second union type to the parameter.

Cannot use %s as value for class constant %s::%s of type %s

Description

This error appears when there is a mismatch between the value of a constant, and its declared type.

Note that there is not type juggling, so the value of the constant must match the type exactly. Consider that strict_types always applies in this case.

Example

<?php

class X {
    const int A = 'abc';
    const int B = '123';
    const int C = 3, D = 'abc';
}

?>

Alternatives

  • Remove the constant type.
  • Replace the constant type.
  • Replace the constant value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use '%s' as namespace name

Description

The namespace keyword is used to declare a namespace, and also to reference the current namespace, when building a name, for a function, a class, etc. As such, it is not possible to use namespace as a prefix of the name of a namespace (sic), as it may be confused later with the current namespace. Also, namespaces are case insensitive.

Example

<?php

namespace Namespace\xyz {}

namespace NAMEspace\xyz {}

// This is OK, as ``namespace`` is not first in the name
namespace Abc\Namespace\Xyz {}

?>

Literal Examples

  • Cannot use “namespace\xyz” as namespace name, due to conflict with ns-relative names

Alternatives

  • Remove the word namespace in the name of the namespace.
  • Add another prefix before the word namespace in the name of the namespace.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use ‘abstract’ as constant modifier

Description

abstract is an option for methods, and it is not available for class constants, properties or enumeration cases.

Example

<?php

class X {
	private static const A  = 1;
}

?>

Alternatives

  • Remove the option from the constant signature.

In more recent PHP versions, this error message is now :ref:cannot-use-the-%s-modifier-on-a-%s.

Cannot use ‘abstract’ as method modifier

Description

When resolving name conflicts during trait imports, it is not possible to use abstract with the as keyword. The situation is actually confusing: abstract may be the name of the alias, or it could also be understood as the modifier.

The same situation arise with abstract, final or readonly. On the other hand, it is valid to use the visibility modifier to actually change the visibility on the alias.

Example

<?php
trait T1 {
	function foo() {}
}
class C1 {
	use T1 {
		T1::foo as abstract;
	}
}
?>

Alternatives

  • Use another name than abstract for the alias.
  • Use another name than abstract for the original method.

In more recent PHP versions, this error message is now :ref:cannot-use-"abstract"-as-method-modifier-in-trait-alias.

Cannot use ‘final’ as constant modifier

Description

final is an option for methods, and it is not available for class constants and properties. It becomes a feature with class constants in PHP 8.0.

Example

<?php

class X {
	private static const A  = 1;
}

?>

Alternatives

  • Remove the option from the constant signature.

In more recent PHP versions, this error message is now :ref:cannot-use-the-%s-modifier-on-a-%s.

Cannot use ‘final’ as method modifier

Description

When resolving name conflicts during trait imports, it is not possible to use final with the as keyword. The situation is actually confusing: final may be the name of the alias, or it could also be understood as the modifier.

The same situation arise with abstract, static or readonly. On the other hand, it is valid to use the visibility modifier to actually change the visibility on the alias.

Example

<?php
trait T1 {
	function foo() {}
}
class C1 {
	use T1 {
		T1::foo as final;
	}
}
?>

Alternatives

  • Use another name than final for the alias.
  • Use another name than final for the original method.

Cannot use ‘mixed’ as class name as it is reserved

Description

mixed is a PHP reserved keyword, since PHP 8.0. Until then, it was possible to use it anywhere as names, but since PHP 8.0, it is forbidden with class names, interfaces, enumerations and traits.

The same error is used for all CITE structures : class, interfaces, traits and enumerations.

Namespaces do not solve this issue.

mixed as a function, method, property, global or class constants is legit.

Example

<?php

class Mixed {}
interface Mixed {}
trait Mixed {}
enum Mixed {}

?>

Alternatives

  • Use another name for that class.

Cannot use ‘namespace’ as namespace name

Description

The namespace namespace keyword introduces a namespace. The namespace may have no name, or a name. The only forbidden name is namespace, as it is used later to identify the current namespace, when used as the first entry in a fully qualified namespace.

Example

<?php

namespace Namespace {}

?>

Alternatives

  • Use another name than namespace.

Cannot use ‘never’ as class name as it is reserved

Description

never is a PHP reserved keyword, since PHP 8.1. Until then, it was possible to use it anywhere as names, but since PHP 8.1, it is forbidden with class names, interfaces, enumerations and traits.

The same error is used for all CITE structures : class, interfaces, traits and enumerations.

Namespaces do not solve this issue.

never as a function, method, property, global or class constants is legit.

Example

<?php

class Never {}
interface Never {}
trait Never {}
enum Never {}

?>

Alternatives

  • Use another name for that class.

Cannot use ‘readonly’ as %s modifier

Description

readonly is reserved for properties, and cannot be used with methods, constants, enumeration cases or static properties.

Example

<?php

class X {
    readonly function foo() {}
}

?>

Literal Examples

  • Cannot use 'readonly' as method modifier
  • Cannot use 'readonly' as constant modifier
  • Cannot use 'readonly' as constant modifier

Alternatives

  • Remove the readonly option from the method signature.

Cannot use ‘readonly’ as method modifier

Description

readonly is reserved for properties, and cannot be used with methods, constants, enumeration cases or static properties.

Example

<?php

class X {
	private readonly function foo() {}
}

?>

Alternatives

  • Remove the option from the method signature.

Cannot use ‘static’ as constant modifier

Description

static is an option for properties and methods, and it is not available for class constants. A class constant is reachable with the name of the class: as such, it behaves like a static class constant by definition: there are not object’s constants.

Example

<?php

class X {
	private static const A  = 1;
}

?>

Alternatives

  • Remove the option from the constant signature.

In more recent PHP versions, this error message is now :ref:cannot-use-the-%s-modifier-on-a-%s.

Cannot use ‘static’ as method modifier

Description

When resolving name conflicts during trait imports, it is not possible to use static with the as keyword. The situation is actually confusing: static may be the name of the alias, or it could also be understood as the modifier.

The same situation arise with abstract, final or readonly. On the other hand, it is valid to use the visibility modifier to actually change the visibility on the alias.

Example

<?php
trait T1 {
	function foo() {}
}
class C1 {
	use T1 {
		T1::foo as static;
	}
}
?>

Alternatives

  • Use another name than static for the alias.
  • Use another name than static for the original method.

Cannot use "%s" as %s as it is reserved

Description

array and callable cannot be used with the leading backslash. This bug was fixed in PHP 8.5.

Example

<?php

// Since PHP 8.5
function foo() : \array {} 

?>

Alternatives

  • Use the type without the leading \.
  • Upgrade to PHP 8.5 (when available).

Cannot use "%s" as %s

Description

This is the generic, truncated form of a family of errors PHP raises when a reserved word is used where an identifier for a class, interface, trait, enum, or type is expected. The first %s is the reserved word as written by the user, the second %s describes the context (class name, interface name, trait name, enum name, a type name, etc.). The full runtime message continues with as it is reserved.

The list of reserved words has grown over time: bool, int, float, string, true, false, null, self, parent and static since PHP 7.0; void and iterable since PHP 7.1; object since PHP 7.2; mixed since PHP 8.0; never since PHP 8.1. array and callable are also reserved for this purpose, although they cannot even reach the parser as identifiers, since they are proper tokens.

The same underlying check is also used, with a different second argument, when a reserved word is written with a leading backslash in a type declaration, such as \array.

Example

<?php

class Int {}
interface Void {}
trait Object {}
enum Iterable {}

?>

Alternatives

  • Use another name; reserved words cannot be used as class, interface, trait, or enum names.
  • Check the exact list of reserved words for the PHP version being targeted.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use "%s" when no class scope is active

Description

self and static refer to the class in which the code is written, respectively as a fixed reference and one resolved at call time (late static binding). Both require an active class scope: they can only be used inside a class, trait, or enum, not in a plain function nor at the top level of a script.

This error appears when self or static is used as a class reference, for instance to instantiate an object, call a static method, or fetch a class constant, outside of any class definition.

Example

<?php

function foo() {
    return new self();
}

?>

Literal Examples

  • Cannot use “self” when no class scope is active
  • Cannot use “static” when no class scope is active

Alternatives

  • Use the actual class name instead of self or static.
  • Move the code inside a class, trait, or enum.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use "::class" on %s

Description

Since PHP 8.0, expr::class can be used on any object expression to retrieve its class name, not only on class names, self, static or parent. When the expression is a scalar literal, such as an integer, float, string or boolean, PHP can already tell at compile time that it will never hold an object, and rejects the construct right away instead of waiting for a runtime error. %s is replaced with a description of the offending value.

Example

<?php

echo 10::class;

?>

Alternatives

  • Only use ::class on a class name, or on an expression that can hold an object.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use "abstract" as method modifier in trait alias

Description

The as clause of a trait use statement can rename a method, and change its visibility (public, protected, private), and, since PHP 8.3, mark it final. It cannot mark the alias abstract, nor static: an alias only renames an existing, concrete method brought in by the trait, it does not declare a new one, so these modifiers make no sense in this context.

This is a compile time check, independent of the class that uses the trait.

Example

<?php

trait T {
    public function foo() {}
}

class X {
    use T {
        foo as abstract bar;
    }
}

?>

Alternatives

  • Remove the abstract modifier from the trait alias.
  • Declare an actual abstract method, in the class or in an interface, instead of trying to alias the trait method as abstract.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use "parent" when current class scope has no parent

Description

parent:: refers to the parent of the class currently being defined. It can only be used inside a class that actually extends another class.

Using parent:: in a class that has no parent (no extends clause) used to only trigger a deprecation notice, in PHP 7.4. Since PHP 8.0, it is a compile time fatal error.

This differs from using parent:: completely outside of any class scope, which is a separate error.

Example

<?php

class Foo {
    public function bar() {
        parent::bar();
    }
}

?>

Alternatives

  • Make the class extend a parent class.
  • Remove the parent:: call, and implement the logic directly in the method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See orphanedParent

Cannot use "parent" when no class scope is active

Description

parent:: can only be used inside a class, trait, or enum, referring to the parent of the class in scope. It cannot be used in a plain function, nor at the top level of a script, where there is no class scope at all.

This differs from using parent:: inside a class that has no parent: that case is a distinct, related error.

Example

<?php

function foo() {
    parent::bar();
}

?>

Alternatives

  • Move the code inside a class that extends another class.
  • Call the target method directly, on an instance or via its class name.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use "static" as method modifier in trait alias

Description

The as adaptation syntax used with use (traits) can only change the visibility of an imported method, or give it a new alias. It cannot be used to add the static modifier to a method: a trait method’s static-ness is fixed by how it is declared in the trait itself, and cannot be altered by the class that imports it.

Example

<?php

trait Greet
{
    public function hello()
    {
        echo 'hi';
    }
}

class X
{
    use Greet {
        hello as static greetStatically;
    }
}

?>

Literal Examples

  • Cannot use “static” as method modifier in trait alias

Alternatives

  • Remove the static modifier from the as adaptation, and only change the visibility or the alias name.
  • Declare the method as static directly in the trait, if that is the intended behavior.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use "yield from" inside a by-reference generator

Description

yield from only emit data by value, not by reference.

Example

<?php

function &foo() {
    yield from [1,2,3];
}

?>

Alternatives

  • Remove the reference sign from the function signature.
  • Refactor the code to use yield instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use ::class with dynamic class name

Description

Until PHP 8.0, it was not possible to use a variable (or any data container) with the ::class operator to get its name. Basically, the name of the class had to be hardcoded.

Example

<?php

$a::class;

?>

Alternatives

  • Use get_class().
  • Use instanceof.

Cannot use [] for reading

Description

The append operator [] is a write operator: it alters the underlying variable. It cannot be used for reading, as it doesn’t produce a value. Hence, it is not possible to use the append operator as an argument, or with a short assignment operator.

Example

<?php

// += needs a value to increment, which [] cannot provide
$a[] += 2; 

// When foo() is called, the value of the arguments is transmitted to the function.
// Here, $a[] has no value.
foo($a[]); 

?>

Alternatives

  • Only use [] in writing context.

Cannot use [] for unsetting

Description

unset() removes a specific, existing element identified by an explicit key. The empty-bracket append syntax ($array[]) only has meaning in a write context, where it picks the next available integer key to create a new element; there is no such “next element” to remove, so combining the two is rejected at compile time.

Example

<?php

$array = [1, 2, 3];
unset($array[]);

?>

Alternatives

  • Pass an explicit key to unset(), e.g. unset($array[2]);.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use a scalar value as an array

Description

Scalar values cannot be modified with the array syntax: for example, it makes no sense to modify the third indexed element on an integer.

The error message is a bit misleading, as strings are allowed to be manipulated that way: some scalar values are allowed. Arrays are, of course, allowed, and for objects, it depends if the class implements ArrayAccess or not.

This error message is used with write context. There is an equivalent error message for reading.

Example

<?php

$a = 123;
$a[3] = 2;

$b = true;
$a[3] = 4;

?>

Alternatives

  • Cast the value to a string.
  • Cast the value to an array.
  • Use a better suited operator than this one.
  • Test the type before using the array syntax on the value.

Cannot use anonymous class in constant expression

Description

PHP 8.1’s “new in initializers” allows object-creation expressions to appear in constant-expression contexts, such as default parameter values, property defaults, static variables, class constants and attribute arguments, as long as the class being instantiated is fixed and unambiguous. An anonymous class is declared and compiled at the exact spot it is written; allowing one inside a shared, deferred context like a property default would raise questions about when and how often it actually gets declared, so it remains disallowed there.

Example

<?php

class Foo {
	public $bar = new class {};
}

?>

Alternatives

  • Give the class a name, declare it separately, and use new Name(…) in the constant expression instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use argument unpacking after named arguments

Description

PHP 8.1 allows named arguments and argument unpacking (…$array) to be combined in the same call, but the unpacked array must come before any named arguments. Argument unpacking supplies its own set of positions/keys, and allowing it to appear after arguments already identified by name would make the resulting parameter order ambiguous, so it is rejected at compile time based on the call’s syntax alone.

Example

<?php

function foo($a, $b, $c) {}

$rest = ['c' => 3];

foo(a: 1, b: 2, ...$rest);

?>

Alternatives

  • Move the unpacked array before the named arguments, adjusting keys as needed: foo(…$rest, a: 1, b: 2);
  • Turn the unpacked array’s values into individual named arguments.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use auto-global as lexical variable

Description

A lexical variable is the variables used in the use part of a closure definition. These variable will be imported in the closure. In this case, the variable is an auto-global variable, which is included in every context, so this is useless.

Example

<?php

    function () use ($_POST) { };

?>

Alternatives

  • Remove the auto-global from the list of imported variable (in the use clause).
  • Remove the use clause, if that variable is there alone.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

cannot use both FILTER_NULL_ON_FAILURE and FILTER_THROW_ON_FAILURE

Description

There are two options for the filter extension to handle errors: either return null, or throw an exception. They are mutually exclusive, and can’t be used at the same time.

Example

<?php

    // combining constants with |
    filter_var( value: 'bob@example.com', 
                filter: FILTER_VALIDATE_EMAIL, 
                options: FILTER_NULL_ON_FAILURE | FILTER_THROW_ON_FAILURE,
                );

    // combining constants with +
    filter_var( value: 'bob@example.com', 
                filter: FILTER_VALIDATE_EMAIL, 
                options: FILTER_NULL_ON_FAILURE + FILTER_THROW_ON_FAILURE,
                );


    // FILTER_NULL_ON_FAILURE + FILTER_THROW_ON_FAILURE = 402653184
    filter_var( value: 'bob@example.com', 
                filter: FILTER_VALIDATE_EMAIL, 
                options: 402653184,
                );

?>

Alternatives

  • Use only one of the two constants.
  • When providing the options as an integer, make sure the bytes 27 and 28 are not set at the same time.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use dynamic class name in constant expression

Description

“New in initializers” (PHP 8.1) lets new SomeClass(…) appear in constant-expression contexts, such as default parameter values, but only when the class name is written literally, or via self/parent, something resolvable without evaluating an arbitrary expression. A dynamic class name taken from a variable or another expression cannot be resolved once and for all in that fixed, deferred context, so it is rejected at compile time.

Example

<?php

$className = 'DateTime';

class Bar {
	public function baz($obj = new $className()) {}
}

?>

Alternatives

  • Use a literal class name instead of a variable.
  • Move the object creation into the function body instead of the parameter default.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use dynamic function name in constant expression

Description

This error appears when the name of the function cannot be entirely resolved at compile time. Here, the array cannot be turned into a function or static method name. This also happens for variations on the name, such as using a boolean, an array, or any expression that cannot be resolved at compilation time.

Example

<?php

const Closure1 = ([])(...);
const Closure2 = (-1)(...);
const Closure3 = (true)(...);

var_dump(Closure);

?>

Alternatives

  • Use a string for the name of the function or static method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use dynamic method name in constant expression

Description

PHP 8.5 allows first-class callable syntax ((...)) to be used inside a constant expression – a global constant, a class constant, a static property default, a parameter default value, and so on – so that a static method can be turned into a Closure at compile time.

To build that closure, the method name must be resolvable at compile time. Here, the braced expression {[1, 2]} is not a simple, literal method name: it is an array, which cannot represent a method name at all. Since the compiler cannot fold it down to a plain string, it reports that a dynamic name was used.

This check only applies to static method calls (X::method(...)); the equivalent restriction for a plain function name is reported as ‘Cannot use dynamic function name in constant expression’. When the braced expression does resolve to a scalar value that simply is not a legal method name (such as an integer), PHP reports ‘Illegal method name’ instead.

Example

<?php

class X {
    public static function foo() { return 1; }
}

const C = X::{[1, 2]}(...);

var_dump(C);

?>

Alternatives

  • Use a literal string for the method name.
  • Move the closure creation out of the constant expression, into ordinary code, where dynamic method names are allowed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See constantExpressionMethodNameResolution85

Cannot use empty array elements in arrays

Description

Arrays can only hold values. There is not meaning in an empty slots in an array.

This problem happens at writing time, and cannot happen at execution time.

This problem looks very similar to the usage of list() with empty slots: yet, list() is allowed to skip all but at least one element. With the modern short syntax of arrays and list, it might be tricky to distinguish them.

Example

<?php

$a = [,,,];
$a = array(,,,);

[,,$x] = [1,2,3];
list(,,$x) = [1,2,3];

?>

Alternatives

  • Spot consecutive commas in an array() syntax.

Cannot use empty array entries in keyed array assignment

Description

The list() (also known as [] on the left side of the = sign), can skip some values, by using consecutive commas. This feature is only available with positional list(), which assign the n-th argument to the n-th element of the array.

Since PHP 7.1, list() accepts named element: this feature match the keys with their equivalent in the array, instead of matching the positions. With that feature, skipping an element in the array is useless: it is also not accepted by the PHP engine.

Example

<?php

$array = ['a' => 1, 3, 'b' => 2];
['a' => $a, , 'b' => $b] = $array;

// valid usage
[$a, , $b] = array_values($array);

?>

Alternatives

  • Remove the extra comma.
  • Remove the keys and use a positional list().

Cannot use empty list

Description

list() must contain at least one non-empty element. Otherwise, it would attempt to load data into no variables, and that makes no sense.

Example

<?php

[,,,] = [1,2,3];
list(,,,) = [1,2,3];

?>

Alternatives

  • Add at least one variable in the list() call.
  • Remove the call to list().

Cannot use isset() on the result of an expression (you can use “null !== expression” instead)

Description

isset() is meant to check the existence of an data container, such as a variable, an array element, a property of an object. It is not meant to check if an expression is null, because it is not a data container.

Expressions are valid with isset within a data container, though.

Example

<?php

$a = 'a';
$b = 'b';
if (isset($a . $b)) {}

// recommended by the error itself
if ($a . $b !== null) {}

// expression are valid with isset within a data container
if (isset($array[$a . $b])) {}
if (isset(${$a . $b})) {}

?>

Alternatives

  • Use a comparison to null with an expression.

Cannot use isset() on the result of an expression

Description

isset() checks whether a data container, such as a variable, an array element or an object property, exists and is not null; it needs an actual container to look up, not a computed value. Concatenating $a and $b produces a plain expression with no container behind it, so isset() cannot be applied to it directly.

Example

<?php

$a = 'a';
$b = 'b';

if (isset($a . $b)) {}

// recommended alternative
if ($a . $b !== null) {}

?>

Alternatives

  • Compare the expression to null instead: $a . $b !== null.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use lexical variable %s as a parameter name

Description

It is not possible to use a parameter and import a variable of the same name. This would result in a naming conflict, and a data overwrite. All names should be distinct.

Example

<?php

function ($a) use ($a) {}; 

?>

Literal Examples

  • Cannot use lexical variable $x as a parameter name

Alternatives

  • Rename the variable in the use clause.
  • Rename the parameter in the function clause.

Cannot use list() as standalone expression

Description

list() assigns values from an array to a list of variables (or data containers). As such, it is a write operation, which should be on the left side of an assignment, or in other write positions, such as a foreach() blind variables or inside another list. list() cannot be used in a read position, as in the code example: list() as not result.

list() also has a short syntax version, []. That short syntax is converted to an array automatically, so it doesn’t yield any error then.

Example

<?php

[list($a)];

// the second [] is not a list() but an array().
[[$a]]; 

?>

Alternatives

  • Use array() or [] instead.

Cannot use list as key element

Description

Since PHP 7.1, foreach can destructure the value of each entry with list() (or its short [] syntax): foreach ($array as $key => list($a, $b)). The key part, on the other hand, is always a single target: a variable, a property, or an array offset. It cannot itself be a list() pattern, since a single array key has nothing to be destructured into several variables.

Example

<?php

$array = [['a', 'b'], 'c', 'd'];

foreach ($array as list($key) => $value) {
}

?>

Literal Examples

  • Cannot use list as key element

Alternatives

  • Use a plain variable for the key, and only destructure the value with list().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

cannot use multiple endian options

Description

The third option of gmp_import() must be either GMP_BIG_ENDIAN, GMP_NATIVE_ENDIAN or GMP_LITTLE_ENDIAN, but not at the same time.

Example

<?php
gmp_import('a', 1, GMP_BIG_ENDIAN | GMP_LITTLE_ENDIAN);
?>

Literal Examples

  • gmp_import(): Argument #3 ($flags) cannot use multiple word order options

Alternatives

  • Use the GMP_NATIVE_ENDIAN.
  • Use the GMP_BIG_ENDIAN.
  • Use the GMP_LITTLE_ENDIAN.
  • Use the default option, by omitting this argument (default is GMP_NATIVE_ENDIAN).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

cannot use multiple word order options

Description

The third option of gmp_import() must be either GMP_MSW_FIRST or GMP_LSW_FIRST, but not at the same time.

Example

<?php
gmp_import('a', 1, GMP_MSW_FIRST | GMP_LSW_FIRST);
?>

Literal Examples

  • gmp_import(): Argument #3 ($flags) cannot use multiple endian options

Alternatives

  • Use the GMP_MSW_FIRST.
  • Use the GMP_LSW_FIRST.
  • Use the default option, by omitting this argument (default is GMP_MSW_FIRST).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use object of type %s as array

Description

An object is not an array: as such, it cannot use the array syntax [1], based on square brackets, but the object syntax, with the object operators -> and ?->.

A class may be made compatible with the array syntax, by implementing the ArrayAccess. Then, it is possible to use the array syntax.

The scalar types are also forbidden to use the array syntax, although they are currently generating a warning, while the same error yields a Fatal Error.

Example

<?php

class X {}

$x = new X;
echo $x[0];

?>

Literal Examples

  • Cannot use object of type x as array

Alternatives

  • Cast the object to array before using the array syntax.
  • Implement the ArrayAccess interface on the class.
  • Use the object operators on the object.

Cannot use object of type stdClass as array

Description

The array syntax $variable[index] is only available for arrays and strings. When used on objects, PHP emits a fatal error.

The boolean false and the null value still accept this behavior. The first is deprecated in PHP 8.1, and the second valid in PHP 8.3.

Example

<?php

$x = new Stdclass();
$x[0] = 1;

?>

Alternatives

  • Check for type before using the array syntax.
  • Keep using consistent types with each variables.
  • Set type with properties to ensure they are consistent.
  • Cast the object to array before usage.

In previous PHP versions, this error message used to be :ref:cannot-unset-offset-in-a-non-array-variable. In more recent PHP versions, this error message is now :ref:cannot-unset-offset-in-a-non-array-variable.

Cannot use positional argument after argument unpacking

Description

It is not possible to put simple arguments after an unpacked argument. Said another way, the unpacked arguments must be the last one in the list.

This happens when using a mix of array unpacking and arguments. It also happens when spreading an array with a mix of numeric and string keys.

Example

<?php

// Valid, the unpacked argument is the last
foo($a, $b, ...$c);

// Also valid, the unpacked arguments are the last
foo($a, $b, ...$c, ...$d);

// Not valid
foo(...$a, $b, ...$c);

// This is invalid, as the numeric arguments are after the 'x'
$a = ['x' => [1], 13, 14];
foo(...$a);

// This is valid, as long as x is not argument 0 or 1. Then, it yields another error.
$a = [13, 14, 'x' => [1]];
foo(...$a);

?>

Alternatives

  • Move the positional arguments to be beginning of the signature call.
  • Sort the unpacked array with krsort() or ksort(), before or after PHP 8.2.
  • Remove the positional arguments.

Cannot use positional argument after named argument during unpacking

Description

This error appears when using an array with a mix of integer and string keys, and spread it as arguments. The actual order of the array is used as the order of the arguments in the function call. Then, integer keys are used as positional arguments, and string keys are as named arguments.

Example

<?php

function foo($a, $b, $c) {}

// unpacking argument, but positional argument is misplaced
$arguments = ['a' => 1, 2, 'c' => 3];
foo(...$arguments);

// make everyone positional. It works since order is already correct
foo(...array_values($arguments));

?>

Alternatives

  • Add the missing argument names to finish the argument array.
  • Move the positional argument to the beginning of the array (array_unshift, or append it at the array creation), when the argument order makes it possible.
  • Use ksort() on the keys, when it makes sense.

Cannot use positional argument after named argument

Description

When using a mix of array unpacking and arguments, it is not possible to put the arguments after the unpacked argument. Said another way, the unpacked arguments must be the last one in the list.

Example

<?php

// Valid, the unpacked argument is the last
foo($a, $b, ...$c);

// Also valid, the unpacked arguments are the last
foo($a, $b, ...$c, ...$d);

// Not valid
foo(...$a, $b, ...$c);

?>

Alternatives

  • Write the positional argument before the named ones in the call.

Cannot use result of built-in function in write context

Description

Binding a reference to the return value of a function ($var = &func();) only makes sense if that function itself returns by reference. Built-in, C-implemented functions never do, and unlike a user-defined function, where forgetting the & in the signature merely triggers a notice at run time, the engine can tell this is impossible for an internal function right away, and raises a compile-time error instead.

Example

<?php

$max = &max(1, 2, 3);

?>

Alternatives

  • Drop the &, and assign the return value normally: $max = max(1, 2, 3);

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use string offset as an array

Description

It is possible to use the array syntax $s[$i] on a string, to access an individual character. And in general, it is also possible to chain the array syntax to access multi-dimensionnal elements $array[1][2].

Yet, the individual characters of a string are not arrays, so it is not possible to use that syntax with them, while reading it from the string.

On the other hand, it is possible to assign the character to a variable: PHP considers it then as a normal string.

Example

<?php

$string = '123';

unset($string[0][1]);

?>

Alternatives

  • Remove the 2nd array syntax when working with a string.
  • Assign the character to a variable, and then use it as a string.

Cannot use string offset as an object

Description

It is possible to use the array syntax $s[$i] on a string, to access an individual character. And in general, it is also possible to chain the array syntax to access properties $array[1]->p.

Yet, the individual characters of a string are never objects, so it is not possible to use that syntax with them, while reading it from the string.

Example

<?php

$string = '123';

unset($string[0]->a);

?>

Alternatives

  • Remove the 2nd array syntax when working with a string.

Cannot use temporary expression in write context

Description

Literal values and constants, global or class, cannot be used for writing: they are immutable. When it is attempted nontheless, this error is displayed.

Those values must be placed in a container, such as a variable, array element, property or static property. That way, they become updatable.

The literal values may be hidden in a returned value, or by a call to native PHP functions which return literals. They may also be hidden in a foreach() call, which does implicit assignments.

This is also the case with the append $variable[] operator, and with object notations on a a constant.

Passing a dimension fetch on a temporary by reference is also not allowed.

The surprising error message comes from the temporary expression built by PHP, to allow a read access to the value. echo A->p; is a read access, while A->p = 3 is a write access.

Example

<?php

// This emits the error
A->p = 3;

// This is a syntax error
// A = 3;

// Attempt to append 1 to an empty literal array
[][] = 1;
array()[] = 1;

$a = array();
$a[] = 1;

$fn = function(&$ref) {};
$fn([0, 1][0]);

function goo() { return [0, 1][0];}
// The constant is hidden in the function goo()
$fn(goo());

function hoo($fn) {
	// PHP provide literal values
	$fn(func_get_args()[0]);
}

?>

Alternatives

  • Store the literal value in a variable, a property or an array index before writing to it.

Cannot use the %s modifier on a %s

Description

This is a generic error message for cases where a keyword cannot be used with a class structure. For example, a class constant cannot be abstract or static.

A special case is using final on a parameter: final is reserved for properties, although properties may be promoted, and also used as a parameter in a constructor. Then, it is not possible to declare the property final, or in the constructor.

final for class constant was also unavailable in PHP 8.0, and it is now a feature.

Example

<?php

class X {
    private final const A = 1;
    private abstract const B = 1;
    private static const C = 1;
    
    function __construct (
        final public $p = 1
    ) {}
}


?>

Literal Examples

  • Cannot use the final modifier on a class constant
  • Cannot use the abstract modifier on a class constant
  • Cannot use the static modifier on a class constant
  • Cannot use the final modifier on a parameter

Alternatives

  • Remove the option from the class constant definition.
  • Upgrade to PHP 8.1 or later, for final on class constants.

In previous PHP versions, this error message used to be :ref:cannot-use-'static'-as-constant-modifier.

Cannot use the abstract modifier on a property hook

Description

It is not possible to make individual property hooks abstract. The keyword must be set at the property definition level, for all the hooks.

Example

<?php

abstract class X {
	public $property {
		abstract get;
	}
}

?>

Alternatives

  • Remove the abstract keyword, and put it on the property definition level.

Cannot use the abstract modifier on a property

Description

Properties cannot be abstract, as they are always available in the class where they are defined.

This will change in PHP 8.4, with property hooks and abstract hooks. Until then, abstract properties are not valid.

Example

<?php

abstract class X {
    public abstract string $x;
}

?>

Alternatives

  • Upgrade to PHP 8.4, and use hooked properties.
  • Remove the abstract keyword.
  • Use magic methods __get and __set to define a custom alternative property.

In more recent PHP versions, this error message is now :ref:only-hooked-properties-may-be-declared-abstract.

Cannot use the final modifier on a parameter

Description

The final option is not available for promoted properties, until PHP 8.5. Until then, the property shall be final but not promoted, or it has to be declared the traditional way.

Example

<?php

class X {
    function __construct( 
        public final int $i
    ) {}
}

?>

Alternatives

  • Upgrade to PHP 8.5 or more recent.
  • Remove the final property from the promoted property.
  • Create the property in the class body.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use the final modifier on a property

Description

When a property is final, it cannot be overridden in a child class; when a class is private, it is only available in the current class.

Hence, a property cannot be final and private at the same time.

In this situation, the property may not final, as there are no property hooks.

Example

<?php

class X {
	final private $property;
}

?>

Alternatives

  • Remove the hooks, and use the magic methods __get/__set.
  • Remove the final keyword.
  • Remove the private keyword and use protected or public.

In more recent PHP versions, this error message is now :ref:property-cannot-be-both-final-and-private.

Cannot use the final modifier on an abstract class

Description

The options final and abstract are mutually exclusive. The first one prevents any redefinition by children, while the second one requests an implementation, and as such, a redefinition, in children classes.

It is the same message, whatever the order of the options.

Example

<?php

final abstract class X {}

abstract final class Z {}

?>

Alternatives

  • Drop the abstract option.
  • Drop the final option.
  • Drop both the options.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use the static modifier on a parameter

Description

It is not possible to use static as a type for a parameter. It is possible for a return value, but not for parameters, not properties.

Example

<?php

    class X {
        function foo(static $argument) {
        
        }
    }

?>

Alternatives

  • Use self pseudo-type.
  • Use the name of the class as type.
  • Use one of the interface as type.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use the static modifier on a property hook

Description

It is not possible to make individual property hooks static. The keyword must be set at the property definition level, for all the hooks.

Example

<?php

class X {
	public $property {
		static get;
	}
}

?>

Alternatives

  • Remove the abstract keyword, and put it on the property definition level.

Cannot use trait %s

Description

An enum’s cases and its constants share a single namespace: a case and a constant cannot have the same name, whether the constant is declared directly in the enum or brought in through a trait.

Here, the trait HasColor declares a constant called Red, and the enum also declares a case called Red; composing the enum with the trait would leave two different things answering to the same name, so PHP refuses to use the trait.

This entry records only the first sentence of the actual engine message, which continues with , because %s::%s conflicts with enum case %s::%s, naming the trait, the constant, the enum and the case involved.

Example

<?php

trait HasColor {
    const Red = 'red';
}

enum Color {
    use HasColor;

    case Red;
}

?>

Literal Examples

  • Cannot use trait HasColor, because HasColor::Red conflicts with enum case Color::Red

Alternatives

  • Rename the constant in the trait so it no longer collides with the enum case.
  • Rename the conflicting case in the enum.
  • Stop using the trait in this enum, and declare the constant directly in the enum, merging it with the case some other way.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use traits inside of interfaces. %s is used in %s

Description

The command use cannot be used in an interface to include a trait. The trait must be included at the class level, or in another trait.

Example

<?php

interface I {
    use T;
}

?>

Literal Examples

  • Cannot use traits inside of interfaces. T is used in I

Alternatives

  • Use the trait in the target classes.

Cannot use try without catch or finally

Description

Try command have catch and finally clauses. While both are optional, they can’t be omitted both at the same time.

Example

<?php

try {}

?>

Alternatives

  • Add a catch clause.
  • Add a finally clause.

Cannot use unpacking in attribute argument list

Description

Attribute arguments are compiled into constant expressions, and evaluated only when the attribute is read through Reflection. The spread/unpacking operator ... needs a runtime array to unpack, which conflicts with this compile time, constant-only nature of attribute arguments.

Unpacking is therefore not allowed in the argument list of an attribute, even when the array being spread only contains constant values.

Example

<?php

#[Attribute]
class MyAttribute
{
    public function __construct(int $a, int $b) {}
}

$args = [1, 2];

#[MyAttribute(...$args)]
class X {}

?>

Alternatives

  • List each argument explicitly, instead of unpacking an array.
  • Use named arguments instead, if this improves readability.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use variable $%pS twice

Description

The use clause of a closure lists the variables imported from the enclosing scope. Each variable can only appear once in that list: importing the same variable twice, whether by value or by reference, is redundant and not allowed.

This is checked at compile time, as the use list is processed.

Example

<?php

function foo() {
    $a = 1;

    return function () use ($a, $a) {
        return $a;
    };
}

?>

Literal Examples

  • Cannot use variable $a twice

Alternatives

  • Remove the duplicate entry in the use clause.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Cannot use variable $%S twice

Description

The same variable cannt be mentioned twice in the use part of a closure definition. This would mean the same argument is defined twice, which is useless.

Example

<?php

$fn = function() use ($a, &$a) {
    $a = 2;
};

?>

Literal Examples

  • Cannot use variable $a twice

Alternatives

  • Make all variables mentioned in the use expression unique (with or without the reference).

Case %s of backed enum %s must have a value

Description

In a backed enumeration, all the cases must have a value. There are no default values for cases, not automatic assignation. This applies to both int and string enumerations.

Example

<?php

enum E: int {
    case A = 1;
    case B;
}

?>

Literal Examples

  • Case B of backed enum E must have a value

Alternatives

  • Add all the missing values to the cases.
  • Remove the type of the enum.

Case %s of non-backed enum %s must not have a value

Description

An enum is either purely a set of named cases (a pure enum), or it is a backed enum, where every case is associated with an int or string value declared after the enum name, like enum Suit: int.

Once an enum does not declare a backing type, none of its cases may be given a value. Assigning a value to a case, like case Hearts = 1;, requires the enum itself to declare a backing type.

Example

<?php

enum Suit
{
    case Hearts = 1;
    case Spades;
}

?>

Literal Examples

  • Case Hearts of non-backed enum Suit must not have a value

Alternatives

  • Remove the value from the case declaration, to keep the enum a pure enum.
  • Add a backing type to the enum declaration, such as enum Suit: int, so every case can carry a value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Case %s::%s does not exist

Description

This error is reported by the Reflection API, when trying to generate the informational object ReflectionEnumUnitCase, with a non-existing Case.

Example

<?php

enum E {
    case a;
}

$reflectionEnum = new ReflectionEnum(E::class);
$reflectionEnum->getCase('b');


?>

Literal Examples

  • Case E::b does not exist

Alternatives

  • Make sure the case exists before trying to instantiate its relate object.

Case can only be used in enums

Description

case is a keyword which is reserved for enumerations enum. It cannot be used in other structures, such as traits, interfaces or classes.

Example

<?php

class X {
    case A = 1;
}

?>

Alternatives

  • Make the class an enumeration.
  • Remove the case from the class.

Case statements followed by a semicolon (;) are deprecated, use a colon (:) instead

Description

It is possible to use a semi-colon ; instead of a colon : after a case in a switch. This is deprecated in PHP 8.5, and will disappear in PHP 9.

Example

<?php

switch($a) {
    case 1;
        echo one;
        break;
}

?>

Alternatives

  • Replace the semicolon by a colon.
  • Do not place a closing tag after a case value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See case-with-semicolon

Charset “%s” is not supported, assuming UTF-8

Description

The provided character set, third argument, is not valid.

Example

<?php

    htmlentities($a, $b, 'xxx');

?>

Literal Examples

  • Charset “xxx” is not supported, assuming UTF-8

Alternatives

  • Use a valid character set.
  • Check for typos, or empty values.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Class “%s” not found

Description

This error message is reported when the class could not be loaded, or when the name of the class is invalid.

It appears when the classes are defined after they are required. It applies to classes in the same file, and never with autoloading.

It also appears when unserializing an enumeration: PHP cannot distinguish a class constant or an enumeration case, so it reports a class error. Yet, this is the enuneration missing.

Example

<?php

// No x definition in the code
new X; 

// it is not possible to have a class, with the name '4f'
('4f')::c;

// it is not possible to have a class, with the name 'class'
('class')::c;

// it is not possible to have static, self or parent in a string to call a method
static::foo();

// unserializing an enumeration, but no such enumration.
print_r(unserialize("a:1:{i:0;E:3:"f:A";}"));


// B is defined after being required by A, so this is a fatal error.
class A extends B {}
class B extends C {}
class C {}
?>

Literal Examples

  • Class “x” not found
  • Class “4f” not found
  • Class “class” not found

Alternatives

  • Check spelling and namespace for that class.
  • Create the required class.
  • Check if the class is defined in an extension, and the extension is included in the current PHP engine.
  • Check if the class is defined in a dependency, and the dependency is included in the current composer.json.
  • Avoid using getInstance() on that attribute.
  • Do not use static, parent or self in a string to call a method statically.
  • Check that the enumeration is loaded.
  • Put classes in different files, and use autoload.

Class %s cannot extend %s %s

Description

A class that is marked final cannot be extended. This error applies to a class that tries to use a final class as parent.

Example

<?php

final class X {}

class Y extends X {}

?>

Literal Examples

  • Class T cannot extend class X

Alternatives

  • Remove the final keyword on the parent class.
  • Use composition in the intended child class.

Class %s cannot extend enum %s

Description

Enum are final classes, and cannot be extended: neither by other enum, nor by a class.

Example

<?php

class X extends E {}

enum E {}

?>

Literal Examples

  • Class X cannot extend enum E

Alternatives

  • Add a class that compose the enum, and extends that class.
  • Remove the extension in the class.

Class %s cannot extend final class %s

Description

A final class is a class that cannot be extended. This means any class that attempts to use extends on this class fails.

This error is produced both by userland code and PHP native code, such as Generator, etc.

Example

<?php

class X extends Generator {}

?>

Literal Examples

  • Class X cannot extend final class Generator

Alternatives

  • Use composition on the final class, to include it in another class.

Class %s cannot implement both Iterator and IteratorAggregate at the same time

Description

This error appears when a class uses two or more interfaces, which are incompatible with one another. The incompatibility is based on name conflicts: two interfaces have a method with the same name.

There is a distinct error for constants. There is the same message for properties, since PHP 8.4.

Example

<?php

class A implements Iterator, IteratorAggregate {}

?>

Literal Examples

  • Class A cannot implement both Iterator and IteratorAggregate at the same time

Alternatives

  • Choose one or the other interface.
  • Use the interface that is compatible with the parent classes.

Class %s cannot implement previously implemented interface %s

Description

It is not allowed to use several times the same interface in a implements clause, for classes, or extends for interfaces.

The message is a bit confusing, since the interface is not already implemented, but rather, used in the implements clause. In fact, PHP checks first the list of names of the clause, then it checks the signatures of the methods.

This error message is dependent on the use expresion, and also the calls to class_alias().

Example

<?php

use I as J;

interface I {}

// Multiple ways to reference an interface
class Foo implements I, \I, J {}

// This applies to interfaces too
interface Bar extends I, \I, J {}

?>

Literal Examples

  • Class foo cannot implement previously implemented interface i

Alternatives

  • Remove the duplicate interface name.

Class %s cannot use %s - it is not a trait

Description

This message comes from zend_class_use_internal_traits(), an internal engine API added to let a C extension attach traits to a class entry it registers, outside of the regular use statement compiled from PHP source (support for traits on internal classes was added late in the PHP 8.6 development cycle). It fires when one of the class entries passed in is not actually a trait.

There is no PHP userland API that reaches this function, so ordinary application code cannot trigger it; it can only show up as the result of a bug in an extension that registers its own classes and passes the wrong class entry as a trait.

The near-identical runtime message, %s cannot use %s - it is not a trait (without the leading word Class), is the one produced by an ordinary use TraitName; inside a PHP class body when TraitName refers to something other than a trait, such as an interface or an ordinary class.

Example

<?php

enum Color {
    case Red;
}

class X {
    use Color;
}

?>

Literal Examples

  • x cannot use Color - it is not a trait

Alternatives

  • If this appears while developing a PHP extension, check the class entries passed to zend_class_use_internal_traits() and make sure each one was registered with ZEND_ACC_TRAIT.
  • If this appears while using a third-party extension, report the issue to its maintainer, since it points to a bug in the extension rather than in the PHP script.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods

Description

A long as there is one absract method in a class, the whole class must be declared abstract. That way, it cannot be instantiated: if a method is missing a body for execution, this definitely must be impossible.

Example

<?php

class X {
    abstract function foo() ; 
}

?>

Literal Examples

  • Class X contains 1 abstract method and must therefore be declared abstract or implement the remaining methods

Alternatives

  • Remove the abstract option on the method(s) and give the a body block.
  • Add the abstract keyword to the class.

Class %s declares abstract method %s() and must therefore be declared abstract

Description

A class that contains an abstract method must also be declared abstract.

Example

<?php

class A {
    abstract function foo() ;
}

?>

Alternatives

  • Remove the abstract method.
  • Remove the abstract option on the method and give it a body.
  • Add the abstract option to the class.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Class %s does not have a property named %s

Description

The reflection extension allows the manipulation of various aspect of existing objects. Yet, it doesn’t allow the assignation of values to non-existing properties, static or not.

Example

<?php
class X { }

$rc = new ReflectionClass('X');
$rc->setStaticPropertyValue('property', 'value');

?>

Literal Examples

  • Class X does not have a property named property

Alternatives

  • Make sure the property exists before trying to assign it a value.
  • Make sure the property is static.

Class %s implementing SessionHandlerInterface is missing the create_sid() method which will be required in PHP 9.0

Description

SessionIdInterface::create_sid() is currently optional: a class only needs it when it also implements SessionIdInterface (as SessionHandler does internally). PHP is moving toward merging SessionIdInterface into SessionHandlerInterface itself, so that every custom session handler is required to provide its own session-id generation strategy. Starting with this deprecation, any class implementing SessionHandlerInterface without a create_sid() method triggers a warning, because in PHP 9.0 the method will become mandatory and its absence will be a fatal error.

Example

<?php

class MySessionHandler implements SessionHandlerInterface {
    public function open($path, $name): bool { return true; }
    public function close(): bool { return true; }
    public function read($id): string|false { return ''; }
    public function write($id, $data): bool { return true; }
    public function destroy($id): bool { return true; }
    public function gc($max_lifetime): int|false { return 0; }
}

session_set_save_handler(new MySessionHandler());
session_start();

?>

Literal Examples

  • Class MySessionHandler implementing SessionHandlerInterface is missing the create_sid() method which will be required in PHP 9.0

Alternatives

  • Add a public create_sid(): string method to the class.
  • Extend SessionHandler instead of implementing SessionHandlerInterface directly; it already provides a default create_sid() implementation.

In more recent PHP versions, this error message is now :ref:class-%s-implementing-sessionhandlerinterface-is-missing-the-validateid()-method-which-will-be-required-in-php-9.0.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See sessionHandlerCompleteInterface

Class %s implementing SessionHandlerInterface is missing the validateId() method which will be required in PHP 9.0

Description

SessionIdInterface::validateId() is currently optional: a class only needs it when it also implements SessionIdInterface (as SessionHandler does internally). PHP is moving toward merging SessionIdInterface into SessionHandlerInterface itself, so that every custom session handler is required to validate incoming session identifiers before they are used. Starting with this deprecation, any class implementing SessionHandlerInterface without a validateId() method triggers a warning, because in PHP 9.0 the method will become mandatory and its absence will be a fatal error.

Example

<?php

class MySessionHandler implements SessionHandlerInterface {
    public function open($path, $name): bool { return true; }
    public function close(): bool { return true; }
    public function read($id): string|false { return ''; }
    public function write($id, $data): bool { return true; }
    public function destroy($id): bool { return true; }
    public function gc($max_lifetime): int|false { return 0; }
}

session_set_save_handler(new MySessionHandler());
session_start();

?>

Literal Examples

  • Class MySessionHandler implementing SessionHandlerInterface is missing the validateId() method which will be required in PHP 9.0

Alternatives

  • Add a public validateId(string $id): bool method to the class.
  • Extend SessionHandler instead of implementing SessionHandlerInterface directly; it already provides a default validateId() implementation.

In previous PHP versions, this error message used to be :ref:class-%s-implementing-sessionhandlerinterface-is-missing-the-create_sid()-method-which-will-be-required-in-php-9.0.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See sessionHandlerCompleteInterface

Class %s is not a trait, Only traits may be used in ‘as’ and ‘insteadof’ statements

Description

It is not possible to use a class name in a use block: the block only uses traits information.

The class method have priority over the trait methods, so there is no need to explicitly solve such conflict. On the other hand, when the trait has to have priority, it has to be specified as such, using a trait name.

Any method defined in a parent class is assimilated to the current class, and has priority.

Example

<?php

class X {}

trait T {}

class Y extends X {
	use T{ X::foo instead of T; }; 
}
?>

Literal Examples

  • Class x is not a trait, Only traits may be used in ‘as’ and ‘insteadof’ statements

Alternatives

  • Remove the use block entry that mentions the class.
  • Fix the name of the class, with the name of a trait.

Class %s must implement interface %s as part of either %s or %s

Description

It is not possible to implement directly the mentioned interface. That interface is actually implemented by a selection of PHP native classes: these classes may be extended, and, as such, the children classes also implements the initial interface.

This error message is applicable to a few PHP native interfaces, such as Throwable (via Error and Exception) and Traversable (via Iterator and IteratorAggregate).

Example

<?php

class X implements Throwable {}

?>

Literal Examples

  • Enum Foo must implement interface Traversable as part of either Iterator or IteratorAggregate
  • Class X cannot implement interface Throwable, extend Exception or Error instead

Alternatives

  • Extends one of the classes mentioned in the error message.
  • Remove the implementats and its interface.

In more recent PHP versions, this error message is now :ref:%s-%s-must-implement-interface-%s-as-part-of-either-%s-or-%s.

Class constant %s::%s cannot have type %s

Description

Some native PHP types are not allowed with a class constant. This is the case of void, never and callable. Any mention of them, alone or in a compsed type generates this error.

Example

<?php

class X {
	const callable|int A = 1;
}

?>

Literal Examples

  • Class constant X::A cannot have type callable|int

Alternatives

  • Remove any illegal type from the definition of the constant.
  • Remove all types from the definition of the constant.

Class declarations may not be nested

Description

It is not allowed to define a class, trait, interface or enum inside another class, trait or enum.

Conditional classes, trait, interfaces or enum may be created, inside if/then, functions and closures, or also loop structures.

The error message is the same for all types of structures, and only mentions class.

Example

<?php

class X {
	function foo() {
		class Y {}
	}
}

?>

Alternatives

  • Use an anonymous class.
  • Use a conditional class, with a if/then, in the global space.
  • Use a function to store the definition and call it at will.

Classes must be first marked as attribute before being able to be registered as internal attribute class

Description

This error could not be reproduced so far. Help us by sending us any generating code.

Example


Alternatives

clone(): Argument #1 ($object) must be of type object, %s given

Description

This is the error message when an attempt of cloning is made on an piece of data that is not an object.

Example

<?php

clone(1);

?>

Literal Examples

  • clone(): Argument #1 ($object) must be of type object, int given
  • clone(): Argument #1 ($object) must be of type object, string given
  • clone(): Argument #1 ($object) must be of type object, array given

Alternatives

  • Check that the cloned value is actually an object.

In previous PHP versions, this error message used to be :ref:clone-method-called-on-non-object.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Closures in constant expressions must be static

Description

When defining a closure as a constant value, there cannot be any context value that are imported. This includes the current object $this which is included by default in any closure. To avoid this, the static option must be added to the closure.

Example

<?php

class X {
    const MY = function () { return 1;}
}

?>

Alternatives

  • Add the static option to the closure.
  • Define the closure inside a method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Constant %s already defined

Description

When a global constant is defined again, PHP reports a warning, and ignores the second definition.

This error applies to global constants only: class constants emit a fatal error, and a different message.

Example

<?php

const A = 1;
const A = 2;

echo A;

define('A', 3);
echo A;

?>

Literal Examples

  • Constant A already defined

Alternatives

  • Remove the second definition.
  • Remove the first definition.
  • Fix the name of one of the constants.
  • Check if there are no missing namespace.

Constant %s is deprecated

Description

This error is emitted when a global constant is supported in the current PHP engine, but will be removed in a future version.

The error is emitted every time the constant is used: it may be for its actual intend, or anywhere else.

Example

<?php

error_reporting(E_STRICT);

?>

Literal Examples

  • Constant E_STRICT is deprecated

Alternatives

  • Stop using that global constant.
  • Find the replacement for this global constant: it might be another constant, or a different command entirely.

Constant %s::%s is deprecated

Description

This error is emitted when a class constant is supported in the current PHP engine, but will be removed in a future version.

The error is emitted every time the class constant is used: it may be for its actual intend, or anywhere else.

The error message is also emitted with the usage of the Deprecated attribute, since PHP 8.4.

Example

<?php

class X {
	#[Deprecated()]
	public const D = deprecated;
}

echo X::D;

?>

Literal Examples

  • Constant X::D is deprecated

Alternatives

  • Stop using that class constant.
  • Find the replacement for this class constant: it might be another constant, or a different command entirely.

Constant expression contains invalid operations

Description

The Constant expressions are the value of a constant, global or class, that is not a literal value. They are calculated.

Constant expressions allows literals, other constants, and most of the operators. Some elements are forbidden: variables, functions, methods and cast operators.

Properties are allowed, but only on enumeration’s cases. New and arrays are allowed, and so does the ternary and coalesce operators, leading to possible conditional constants expressions (sic). Magic constant are also OK.

Example

<?php

class X {
	// invalid, because of the usage of the variable
	const X = $a;
}

?>

Alternatives

  • Remove the invalid elements or operations.

Constructor %s::%s() cannot declare a return type

Description

There can be no return type for a constructor method. It is called while creating a new instance of an object, but it doesn’t return the object itself. This is the case even if $this is available in the method.

Example

<?php

class X {
	function __construct() : int {
	
	}
}

?>

Literal Examples

  • Constructor X::__construct() cannot declare a return type

Alternatives

  • Remove the return type of the method.

In more recent PHP versions, this error message is now :ref:method-%s::__construct()-cannot-declare-a-return-type.

contains an invalid cURL option

Description

curl_setopt() uses a cURL option as second parameter. These options are PHP native constants, and use the prefix CURLOPT_, which resolve to an integer.

It is possible to use the equivalent integer to set a cURL option, for example via a variable. The value of this variable must be checked to be a valid cURL constant before usage.

Using another type instead of a cURL constant is reported as an error of type.

Example

<?php

$ch = curl_init(http://www.example.com/);
$fp = fopen(example_homepage.txt, w);

curl_setopt($ch, 12332, $fp);
curl_setopt($ch, 'abc', $fp);

?>

Alternatives

  • Use the CURLOPT_* constant.
  • Check that the intended value may be resolved as a CURLOPT_* constant (CURLOPT_APPEND === 50, so 50 may be used; etc.).

continue“ targeting switch is equivalent to “break

Description

The recommendation is to use break inside a switch, and continue in loops. Both keywords achieve the same feature of terminating the current structure and following up with the execution, they carry different human meanings.

Example

<?php
    
switch($a) {
    case 1:
        continue;
}

?>

Alternatives

  • Use break.

continue operator accepts only positive integers

Description

continue indicates the number of nested loop to continue in. The minimum is 1. 0 would be a no operation, and shall be skipped. Negative numbers or decimals make no sense.

Example

<?php

$a = [];
foreach($a as $b) {
    continue 0;
    
}
?>

Alternatives

  • Remove the continue command.
  • Remove the 0.

Could not check compatibility between %s and %s, because class %s is not available

Description

This error message signals that PHP could not find all the needed classes and interfaces to reach a conclusion about the compatibility of V, compared to W.

PHP checks all the classes and interfaces whose definitions are already known, and, eventually, calls autoload to get the missing classes. When all avenues are exhausted, PHP yields this error.

In fact, if checking compatibility fails, the code will not run later anyway.

Example

<?php

class V {
    function foo() : X { }
}

class W extends W {
    function foo() : Y { }
}

?>

Literal Examples

  • Could not check compatibility between V::foo() and W::foo(), because class X is not available

Alternatives

  • Use existing classes or interfaces as type.
  • Fix typos in type names.
  • Add any missing class or interface.

Could not find trait %s

Description

A trait is named in a use expression inside a class, but it doesn’t exist, or is not yet loaded by PHP.

The trait may be included in a different use expression. Then, it generates a distinct error message.

Note that when the trait exists and is known to PHP, there is a distinct error message.

Example

<?php
trait A {
    public function foo(){}
}

class B {
    use A {
        C::foo as tf;
    }
}

?>

Literal Examples

  • Could not find trait C

Alternatives

  • Remove the expression that mentions the non-existing trait.
  • Create the missing trait.
  • Add the trait to the class.

Couldn’t open stream %s

Description

When opening a stream, or file, a mode of operation is needed.

There are several valid modes: ‘r’, ‘r+’, ‘w’, ‘w+’, ‘a’, ‘a+’, ‘x’, ‘x+’, ‘c’, ‘c+’, ‘e’. Check docs for details about them.

All other strings are not supported, and yield this error.

Example

<?php

//`+k' is not a valid mode for fopen 
// k is not an open option
fopen($path, '+k');

//`+wr' is not a valid mode for fopen 
// write-only w, read-only r and + are mutually exclusive
// w+, r+ and rw are all valid
fopen($path, '+wr');


?>

Alternatives

  • Use only valid stream open modes.

In more recent PHP versions, this error message is now :ref:couldn't-open-stream:-%s.

Couldn’t open stream: %s

Description

When opening a stream, or file, a mode of operation is needed.

There are several valid modes: ‘r’, ‘r+’, ‘w’, ‘w+’, ‘a’, ‘a+’, ‘x’, ‘x+’, ‘c’, ‘c+’, ‘e’. Check docs for details about them.

All other strings are not supported, and yield this error.

Example

<?php

//`+k' is not a valid mode for fopen 
// k is not an open option
fopen($path, '+k');

//`wr' is not a valid mode for fopen 
// write-only w and read-only r are mutually exclusive
fopen($path, 'wr');


?>

Literal Examples

  • Couldn’t open stream: ‘+k’ is not a valid mode for fopen
  • Couldn’t open stream: Is a directory
  • Couldn’t open stream: Inappropriate ioctl for device
  • Couldn’t open stream: Invalid argument

Alternatives

  • Use only valid stream open modes.

In previous PHP versions, this error message used to be :ref:couldn't-open-stream-%s.

Creating default object from empty value

Description

This deprecation message is emitted in PHP 7.x to signal that an object was created without instantiation. In the illustration code, $x does not exist before assigning it a property a, and a value. The created object is stdClass.

This error is specific to the creation of the variable: if $x was set with null, a different message was emitted.

Example

<?php

$x->a = 1;

?>

Alternatives

  • Explicitly create the object before accessing its properties.
  • Cast an array to (object).
  • Instanciate a stdClass.

In more recent PHP versions, this error message is now :ref:attempt-to-assign-property-"%s"-on-null.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See creatingObjectOnNull

Creation of dynamic property %s::$“ ZEND_LONG_FMT “ is deprecated

Description

This is the numeric-key twin of the more common Creation of dynamic property %s::$%s is deprecated notice. It fires when the property key being written is an integer rather than a string – most often while restoring an object with unserialize() from data whose property key was encoded as i:N; instead of the usual s:len:"name";. Since the class does not declare a property named after that integer and has not opted in with #[AllowDynamicProperties], PHP falls back to creating a dynamic property, but flags it as deprecated just like any other undeclared property write.

As of PHP 8.2, this deprecation also closes a gap where such integer-keyed properties could otherwise bypass the dynamic-property protections entirely.

Example

<?php

class Foo {
}

// PHP's serialization format allows an object property key to be
// stored as an integer ('i:0;') instead of a string ('s:1:"0";').
$serialized = 'O:3:"Foo":1:{i:0;s:1:"x";}';

$foo = unserialize($serialized);
var_dump($foo);

?>

Literal Examples

  • Creation of dynamic property Foo::$0 is deprecated

Alternatives

  • Declare the property in the class definition so the key, once cast to string, matches a known property.
  • Add the #[AllowDynamicProperties] attribute to the class if dynamic properties are intentional.
  • Sanitize or validate serialized data before calling unserialize(), rather than trusting arbitrary property keys.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See dynamicProperties

Creation of dynamic property %s::$%s is deprecated

Description

When PHP uses an undefined property for a writing access, it used to create that property on the fly. The property is created with public visibility, not type nor default value.

Since PHP 8.2, this is a deprecated feature. In a later version, by default, dynamic properties will be forbidden, and activated case by case, using sdtClass or the #[AllowDynamicProperties] attribute.

Example

<?php

class X {
    public $property = 1;
}

$x = new X;
$x->property = 2;
// This is a dynamic property
$x->other = 3;

?>

Alternatives

  • Declare the property in the class definition.
  • Create an array and store the properties there.
  • Create a stdClass object and store the properties there.
  • Add the #[AllowDynamicProperties].

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See dynamicProperties

CURLPIPE_HTTP1 is deprecated

Description

CURLPIPE_HTTP1 is a flag that used to enable HTTP/1.1 pipelining when passed to curl_multi_setopt() with the CURLMOPT_PIPELINING option. Support for HTTP/1.1 pipelining was removed from libcurl itself in version 7.62.0, because it proved fragile and was superseded by HTTP/2 multiplexing.

When PHP is linked against a libcurl older than 7.62.0, setting this flag still works but now raises an E_DEPRECATED notice. When linked against libcurl 7.62.0 or later (the common case on current systems), the same code instead raises an E_WARNING stating that CURLPIPE_HTTP1 is no longer supported, and the flag has no effect either way.

Example

<?php

$mh = curl_multi_init();
curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_HTTP1);

?>

Alternatives

  • Remove CURLPIPE_HTTP1 from the value passed to curl_multi_setopt($mh, CURLMOPT_PIPELINING, ...).
  • Use CURLPIPE_MULTIPLEX to enable HTTP/2 multiplexing instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See curl_multi_setopt

Current function is not a closure

Description

The Closure::getCurrent() method may only be called inside a closure or an arrow function.

This error message also applies to methods.

Example

<?php

function foo() {
    echo Closure::getCurrent();
}

foo();

?>

Alternatives

  • Remove the call to Closure::getCurrent() from the function.
  • Turn the funciton into a closure or an arrow function.

DateTimeInterface can’t be implemented by user classes

Description

DateTimeInterface is an interface. It should be available for usage with the implements keyword, but the PHP engines forbids it. Instead, it is recommended to extends the DateTime or DateTimeImmutable classes.

On the other hand, DateTimeInterface is available to type arguments, properties, etc. or to use with instanceof and catch.

Example

<?php

class X implements DateTimeInterface {}

?>

Alternatives

  • Extends DateTime class.
  • Extends DateTimeImmutable class.

DateTimeZone object is unconstructed

Description

IntlTimeZone::fromDateTimeZone() converts a DateTimeZone object into an IntlTimeZone one. To do so, it reads the internal timezone data that DateTimeZone::__construct() normally sets up.

If it is given a DateTimeZone instance that was created without going through its constructor – for example via ReflectionClass::newInstanceWithoutConstructor(), or an object left in a broken state after a failed unserialize() – that internal data is missing, and the conversion cannot proceed.

Example

<?php

$tz = (new ReflectionClass(DateTimeZone::class))->newInstanceWithoutConstructor();

// The object exists, but __construct() was never called
IntlTimeZone::fromDateTimeZone($tz);

?>

Alternatives

  • Always create the DateTimeZone with new DateTimeZone($identifier) rather than bypassing its constructor.
  • If the object comes from unserialization, verify it succeeded and produced a valid object before using it.
  • Wrap the call in a try/catch (Error) if the DateTimeZone instance’s origin cannot be controlled.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Declaration of %s must be compatible with %s

Description

Classes methods signature have to be compatible between a parent class and a child class. When the signatures are different, the caller has to figure out which object is being used, and how to call the method. Hence, PHP checks that methods are compatible.

Method signature compatibility applies to all methods, except for __construct, which may have completely different signatures one from another.

The error message requires compatible signatures, which means that some variations are possible, and others are not.

Authorized variations

  • Add a new parameter, with a default value
  • Make the returntype more general than the parent
  • Make the parameter types stricter than the parent
  • Add elements to a union type of a parameter
  • Change the default value
  • Change the names of the parameters (not recommended)
  • Make the visibility stricter

Forbidden variations

  • Add or remove a parameter
  • Add or remove a default value
  • Add or remove a parameter type
  • Add or remove the return type
  • Add or remove the reference option
  • Add or remove the variadic option
  • Add or remove the static option.

Example

<?php

class X {
    function foo($a) {}
    
}

class Y extends X {
    function foo() {}
    
}
?>

Literal Examples

  • Declaration of x::foo() must be compatible with y::foo()

Alternatives

  • Check the variations and fix them.
  • Change the name of the method to a free one.

Declaration of %s::%s() must be compatible with %s::%s()

Description

Classes methods signature have to be compatible between a parent class and a child class. When the signatures are different, the caller has to figure out which object is being used, and how to call the method. Hence, PHP checks that methods are compatible.

Method signature compatibility applies to all methods, except for __construct, which may have completely different signatures one from another.

The error message requires compatible signatures, which means that some variations are possible, and others are not.

Authorized variations

  • Add a new parameter, with a default value
  • Make the returntype more general than the parent
  • Make the parameter types stricter than the parent
  • Add elements to a union type of a parameter
  • Change the default value
  • Change the names of the parameters (not recommended)
  • Make the visibility stricter

Forbidden variations

  • Add or remove a parameter
  • Add or remove a default value
  • Add or remove a parameter type
  • Add or remove the return type
  • Add or remove the reference option
  • Add or remove the variadic option
  • Add or remove the static option.

Example

<?php

class X {
    function foo($a) {}
}

class Y extends X {
    function foo() {}
}
?>

Literal Examples

  • Declaration of y::foo() must be compatible with x::foo()

Alternatives

  • Check the variations and fix them.
  • Change the name of the method to a free one.

Declaration of case-insensitive constants is no longer supported

Description

The define() function used to create case sensitive and case insensitive constants. This was the usage of the third parameter.

Since PHP 8.0, only case sensitive constants may be declared, with const and with define().

Example

<?php

// the third parameter is now ignored
define('CONSTANT_NAME', 'constant value', true);

?>

Alternatives

  • Declare variations of the constant name.

declare(%s) value must be a literal

Description

declare() directives (ticks, encoding, strict_types) are processed by the compiler while the file is being parsed, before any code actually runs. At that point, constants, variables, and function calls are not yet available, so only a literal value, such as 1, 0, or a quoted string, can be given as the directive’s value.

This applies equally to every directive: ticks, encoding, and strict_types all require a literal.

Example

<?php

define('TICK_VALUE', 1);

declare(ticks = TICK_VALUE) {
    echo 'Done';
}

?>

Literal Examples

  • declare(ticks) value must be a literal
  • declare(strict_types) value must be a literal
  • declare(encoding) value must be a literal

Alternatives

  • Replace the constant, variable, or expression with its literal value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Declaring %s constant called namespace is deprecated

Description

namespace is a reserved word in PHP, but a historical lexer exception let it be used as the name of a class, interface, trait or enum constant, as well as a static property. PHP 8.6 deprecates that exception for constants, so that namespace can be reserved for a possible future ::namespace pseudo-constant, analogous to the existing ::class.

The deprecation notice is emitted when the constant is declared, not when it is used.

Example

<?php

class Foo {
    const NAMESPACE = 'bar';
}

echo Foo::NAMESPACE;

?>

Literal Examples

  • Declaring class constant “namespace” is deprecated
  • Declaring interface constant “namespace” is deprecated
  • Declaring enum constant “namespace” is deprecated

Alternatives

  • Rename the constant to something other than NAMESPACE.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, namespace could be freely used as the name of a class/interface/trait/enum constant. As of PHP 8.6, declaring it emits a deprecation notice, reserving the word for a possible future ::namespace pseudo-constant.](Previously, namespace could be freely used as the name of a class/interface/trait/enum constant. As of PHP 8.6, declaring it emits a deprecation notice, reserving the word for a possible future ::namespace pseudo-constant.)

Decrement on empty string is deprecated as non-numeric

Description

The -- operator has special, Perl-inspired handling for strings: decrementing a numeric string decrements the number, and historically decrementing a non-numeric string (including the empty string) was silently treated as if it were 0, so ''-- produced -1. This ‘consider as 0’ behaviour is surprising, since it makes -- on a string do something completely different from what ++ does on the very same string.

As of PHP 8.3, decrementing an empty string emits this deprecation notice; the value is still coerced to 0 before the decrement for backward compatibility, but this implicit behaviour is intended to go away in PHP 9.0, as part of a broader effort to make ++/-- on strings saner and introduce str_increment() / str_decrement().

Example

<?php

$str = '';
$str--;
var_dump($str);

?>

Alternatives

  • Check for an empty string explicitly before decrementing, and handle it as its own case rather than relying on the implicit 0.
  • Cast to int first if a numeric decrement was actually intended: $n = (int) $str; $n–;
  • Use str_decrement() when the goal is Perl-style string decrementing rather than numeric decrementing.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Decrement on non-numeric string has no effect and is deprecated

Description

Unlike ++, which performs a Perl-style alphanumeric string increment (turning 'z' into 'aa', for example), the -- operator was never given an equivalent behaviour for non-numeric strings: applying it to something like 'abc' simply leaves the string untouched. That asymmetry – ++ transforms the string but -- silently no-ops – is confusing and easy to miss, since no warning was previously raised.

As of PHP 8.3, decrementing a non-numeric, non-empty string emits this deprecation notice so the no-op is no longer silent. The string itself is still left unchanged, but relying on that will trigger a warning today and is expected to change behaviour in PHP 9.0.

Example

<?php

$str = 'abc';
$str--;
var_dump($str);
// still string(3) "abc" -- the decrement had no effect at all

?>

Alternatives

  • Do not use – on strings that are not guaranteed to be numeric; check is_numeric() first if the intent really is arithmetic.
  • If the goal was a Perl-style string decrement, use str_decrement() instead, which raises a ValueError for invalid input rather than doing nothing.
  • Cast to int explicitly if an arithmetic decrement starting from 0 was intended: $n = (int) $str; $n–;

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Decrement on type bool has no effect, this will change in the next major version of PHP

Description

Post decrement on a boolean leaves the value unchanged. While PHP updates strings, integers, floats with the post-decrement operator, booleans are immune.

Until PHP 8.3, it was silently done. In PHP 8.3, it raises a deprecation warning, and it will be removed in PHP 9.0.

Post increment, pre increment, as well as increment and decrement are affected by that warning. str_increment() and str_decrement() refuses to use boolean, due to type.

Example

<?php

$a = true;
$a++;
// $a = true

$b = false;
--$b;
// $b = false

?>

Alternatives

  • Avoid initializing variables with booleans before decrementing them.
  • In case of doubt, check the type before the decrement.

Decrement on type null has no effect, this will change in the next major version of PHP

Description

Pre or post increment on a null leaves the value unchanged. While PHP updates strings, integers, floats with the post- or pre-increment operators, null are immune.

Until PHP 8.3, it was silently done. In PHP 8.3, it raises a deprecation warning, and it will be removed in PHP 9.0.

Post increment, pre increment, as well as increment and decrement are affected by that warning. str_increment() and str_decrement() refuses to use null, due to type.

Example

<?php

$a = null;
$a--;
--$a;
// $a === null

?>

Alternatives

  • Avoid initializing variables with null before decrementing them.
  • In case of doubt, check the type before the increment.

Default value for parameters with a %s type can only be %s or NULL

Description

The default value of the parameter is not compatible with the type of the same parameter. In the example here, the parameter $s is supposed to be an integer, but has a string as default value.

This error also applies to numeric strings: the default value must be of the same type, without any silent type juggling.

Example

<?php

function foo(int $s = 's') { }

function bar(int $s = '1') { }

?>

Alternatives

  • Change the type of the parameter.
  • Change the default value.
  • Change the default value to NULL.
  • Remove the default value.
  • Remove the type value.
  • Add a second union type to the parameter.

In more recent PHP versions, this error message is now :ref:cannot-use-%s-as-default-value-for-parameter-$%s-of-type-%s.

Default value for property of type %s may not be null. Use the nullable type %s to allow null default value

Description

Typed properties can have a default value, but that default value must match the declared type. null is only a valid default when the type is explicitly nullable, written with a leading ?, such as ?int.

Without the ?, a scalar or class type like int or X does not accept null, even as a default value that is never read before being overwritten.

Example

<?php

class X
{
    public int $value = null;
}

?>

Literal Examples

  • Default value for property of type int may not be null. Use the nullable type ?int to allow null default value

Alternatives

  • Make the property type nullable, for example ?int instead of int.
  • Remove the default value, and initialize the property in the constructor instead.
  • Use a non-null default value that matches the declared type.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Default value for property of type int may not be null. Use the nullable type ?int to allow null default value

Description

When an argument is typed, and has a null default value, PHP makes it automagically nullable. That is not the case for properties, which yields this error.

Example

<?php

class X {
	private int $i = null;
}

function foo(int $i = null) { }

?>

Alternatives

  • Add the nullable type to the type definition.
  • Use another default value, within the current type domain.

define(): Argument #3 ($case_insensitive) is ignored and treated as false since declaration of case-insensitive constants is no longer supported, passing the argument explicitly is unnecessary

Description

Case-insensitive constants were deprecated in PHP 7.3 and their support was removed in PHP 8.0: the third argument of define() has been ignored and always treated as false ever since. This deprecation goes one step further and flags every explicit call that still passes a (falsy) value for $case_insensitive, since doing so no longer has any effect and only adds noise to the call.

Example

<?php

define('FOO', 'bar', false);

?>

Literal Examples

  • define(): Argument #3 ($case_insensitive) is ignored and treated as false since declaration of case-insensitive constants is no longer supported, passing the argument explicitly is unnecessary

Alternatives

  • Call define() with only two arguments: the constant name and its value.

In more recent PHP versions, this error message is now :ref:define():-argument-#3-($case_insensitive)-is-ignored-since-declaration-of-case-insensitive-constants-is-no-longer-supported,-this-will-be-an-error-in-php-9.0.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See caseInsensitiveConstant

define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported, this will be an error in PHP 9.0

Description

Case-insensitive constants were deprecated in PHP 7.3 and their support was removed in PHP 8.0: passing true as the third argument of define() no longer makes the constant case-insensitive, and is simply ignored. This deprecation warns that the leniency is temporary: in PHP 9.0, passing a truthy value for $case_insensitive will stop being silently ignored and will instead raise a fatal error.

Example

<?php

define('FOO', 'bar', true);

?>

Literal Examples

  • define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported, this will be an error in PHP 9.0

Alternatives

  • Call define() with only two arguments: the constant name and its value.
  • Use the const keyword instead of define() if the constant does not need to be defined conditionally.

In previous PHP versions, this error message used to be :ref:define():-argument-#3-($case_insensitive)-is-ignored-and-treated-as-false-since-declaration-of-case-insensitive-constants-is-no-longer-supported,-passing-the-argument-explicitly-is-unnecessary.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See caseInsensitiveConstant

define(): Argument #3 ($case_insensitive) is ignored since declaration of case-insensitive constants is no longer supported

Description

The third argument of define() used to allow the creation of a case-insensitive global constant. The constant in the code would have been accessible with A or a, without distinction. This feature has been deprecated in PHP 7.3 and abandoned in PHP 8.0. For backward compatibility, the third argument is not reported as an error, but a warning. The constant is not case insensitive any way. Adding a fourth argument is a fatal error, and has no meaning.

Example

<?php

define('A', 'b', true);

?>

Alternatives

  • Remove the third argument in the define() call.

In previous PHP versions, this error message used to be :ref:define():-declaration-of-case-insensitive-constants-is-deprecated.

define(): Declaration of case-insensitive constants is deprecated

Description

The third argument of define() used to allow the creation of a case-insensitive global constant. The constant in the code would have been accessible with A or a, without distinction. This feature has been deprecated in PHP 7.3 and abandoned in PHP 8.0. For backward compatibility, the third argument is not reported as an error, but a warning. The constant is not case insensitive any way. Adding a fourth argument is a fatal error, and has no meaning.

Example

<?php

define('A', 'b', true);

?>

Alternatives

  • Remove the third argument in the define() call.

In more recent PHP versions, this error message is now :ref:define():-argument-#3-($case_insensitive)-is-ignored-since-declaration-of-case-insensitive-constants-is-no-longer-supported.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See caseInsensitiveDefine

Defining a custom assert() function is not allowed,

Description

assert() is a PHP native function, used to create assertions. To avoid confusion, or redefinition of this function, it is not allowed to create a custom version of this function, even in a namespace.

Example

<?php

namespace X;

function assert() {}

?>

Alternatives

  • Give another name to that function.
  • Make it a method.
  • Make it a Closure.

Delimiter must not be alphanumeric, backslash, or NUL byte

Description

The first character of a regex is the delimiter, that delimits the regex. There is a first and a last delimiter.

In the case of this error, the first regex character is of invalid type. It cannot be alphanumeric (a-z, A-Z and digits), the backslash \ nor the nul byte chr(0).

Note that if the first characters are white spaces, such as space, tabulation, new line, they are ignored as potential delimiter.

Example

<?php

preg_match('a[bc]a', 'abc');

?>

Alternatives

  • Use a non-alphanumeric character, like /, #.

In previous PHP versions, this error message used to be :ref:delimiter-must-not-be-alphanumeric,-backslash,-or-nul.

Delimiter must not be alphanumeric, backslash, or NUL

Description

The first character of a regex is the delimiter, that delimits the regex. There is a first and a last delimiter.

In the case of this error, the first regex character is of invalid type. It cannot be alphanumeric (a-z, A-Z and digits), the backslash \ nor the nul byte chr(0).

Note that if the first characters are white spaces, such as space, tabulation, new line, they are ignored as potential delimiter.

Example

<?php

preg_match('a[bc]a', 'abc');

?>

Alternatives

  • Use a non-alphanumeric character, like /, #.

In previous PHP versions, this error message used to be :ref:delimiter-must-not-be-alphanumeric-or-backslash. In more recent PHP versions, this error message is now :ref:delimiter-must-not-be-alphanumeric,-backslash,-or-nul-byte.

Delimiter must not be alphanumeric or backslash

Description

The first character of a regex is the delimiter, that delimits the regex. There is a first and a last delimiter.

In the case of this error, the first regex character is of invalid type. It cannot be alphanumeric (a-z, A-Z and digits), nore the backslash \.

Note that if the first characters are white spaces, such as space, tabulation, new line, they are ignored as potential delimiter.

Later, the NUL character (chr(0)) was added to the list of the forbidden characters.

Example

<?php

preg_match('a[bc]a', 'abc');

?>

Alternatives

  • Use a non-alphanumeric character, like /, #.

In more recent PHP versions, this error message is now :ref:delimiter-must-not-be-alphanumeric,-backslash,-or-nul.

Deriving $_SERVER[‘argv’] from the query string is deprecated. Configure register_argc_argv=0 to turn this message off

Description

When the register_argc_argv INI directive is enabled and PHP is running under a non-CLI SAPI (such as CGI/FastCGI), $_SERVER['argv'] and $_SERVER['argc'] used to be reconstructed from the raw query string, splitting it on + the same way a shell would split command-line arguments. This behaviour only makes sense for the CLI SAPI, where a real argument vector exists, and is now deprecated for every other SAPI.

To reproduce this message, run a script under the CGI SAPI with a non-empty query string, for instance: php-cgi -d register_argc_argv=1 with QUERY_STRING=foo=bar set in the environment, the way a web server would when forwarding a request.

Example

<?php

    var_dump($_SERVER['argv']);

?>

Alternatives

  • Set register_argc_argv=0 in php.ini to silence the message; $_SERVER['argv'] will simply not be populated outside of the CLI SAPI.
  • Use $_GET to read individual query string parameters instead of parsing $_SERVER['argv'].
  • Use $_SERVER['QUERY_STRING'] if the raw, unparsed query string is needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See register_argc_argv

Destructors cannot declare a return type

Description

There can be no return type for a destructor method. It is called while destroying an existing instance of an object, and the object won’t be available at the end.

Example

<?php

class X {
	function __destruct() : int {}
}

?>

Alternatives

  • Remove the return type of the method.

Direct instantiation of WeakReference is not allowed, use WeakReference::create instead

Description

A WeakReference holds a reference to an object without preventing that object from being destroyed. Such objects must be created with the static method WeakReference::create(), which takes the object to watch as its argument. The new WeakReference() syntax is not allowed, and it throws an Error.

WeakReference::create() also returns the same WeakReference instance each time it is called with the same object, so comparing two references with === tells whether they point to the same object.

Example

<?php

$object = new stdClass();

// WeakReference objects can only be created with WeakReference::create()
$reference = new WeakReference();

?>

Literal Examples

  • Direct instantiation of WeakReference is not allowed, use WeakReference::create instead

Alternatives

  • Replace new WeakReference($object) with WeakReference::create($object).
  • Once created, call get() on the reference to retrieve the object, or null if it has been destroyed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Directive ‘report_memleaks’ is deprecated

Description

report_memleaks controls whether the Zend Memory Manager reports memory leaks detected during an unclean shutdown (for example when a fatal error occurs). This diagnostic is only meaningful on debug builds of PHP, since a production, non-debug build does not track individual allocations well enough to produce a useful report.

Because the directive is only relevant to internal debugging builds and not to application code, it is deprecated as of PHP 8.5.0.

Example

<?php

ini_set('report_memleaks', '0');

?>

Alternatives

  • Remove references to report_memleaks from php.ini and from the code; the directive has no practical effect on non-debug builds.
  • Use a dedicated memory profiler (e.g. Valgrind, a debug build of PHP) when investigating memory leaks.

Disabling session.use_only_cookies INI setting is deprecated

Description

session.use_only_cookies is marked for deprecation. When that directive will be removed, the feature will be set to always on.

Example

<?php

if (!ini_get('session.use_only_cookies')) {
    die('it is recommended to only use cookies for sessions.');
}

?>

Alternatives

  • Set session.use_only_cookies to on in php.ini.
  • Remove usage of ini_get() with session.use_only_cookies in the code.
  • Remove usage of ini_set() with session.use_only_cookies in the code.

Division of PHP_INT_MIN by -1 is not an integer

Description

In the specific case of the integer division of PHP_MIN_INT by -1, a specific error is reported: the result is not an integer.

In fact, - PHP_INT_MIN = PHP_INT_MAX + 1: PHP_INT_MIN is larger than PHP_INT_MAX, in absolute value. It implies that multiplying, or dividing it by -1, cannot be represented as a integer.

Since the intdiv() has a return type of int, returning a float is not possible. Hence, the specific error.

Any other argument is valid, as it will be within the range of the integers.

Last, using the / operator works, since the operator doesn’t have a return type.

Example

<?php

intdiv(PHP_MIN_INT, -1);

?>

Alternatives

  • Check both operands before feeding them to the intdiv() function.
  • Use /, and then check if it is an integer or not.
  • Convert the values to float, and then, convert the result of the division to integer.

Duplicate declaration of static variable $%s

Description

It is not allowed anymore to declare twice a static variable in a method. This is spotted at compile time.

Example

<?php

function foo() {
	static $a;
	
	++$a;
	
	static $a;
}

?>

Literal Examples

  • Duplicate declaration of static variable $a

Alternatives

  • Remove all the static declarations, but one: keep the earliest one.

Duplicate named parameter $%s

Description

Parameter shall only be passed once. For named parameters, this means that the same name shall only be used once when calling the method.

This problem is never raised with positional arguments, which are automatically indexed.

There is a distinct error message when this happens to in method calls.

Example

<?php

function foo($b, $b) {}

#[MyAttribute(a: 'A', a: 'A')]
class Test {}

?>

Literal Examples

  • Duplicate named parameter $a
  • Duplicate named parameter $b

Alternatives

  • Remove the names of the parameters.
  • Change the name of all the duplicate named parameters, but one.
  • Remove the duplicates named parameters, but one.

Duplicate parameter name $%s for function %s%s%s()

Description

It is not allowed to have several times the same parameter in a method, closure or function signature. All the parameters must have different names.

This error appears only in PHP debug mode.

Example

<?php

function foo($a, $a, $a) {}

?>

Literal Examples

  • Duplicate parameter name $a for function foo()

Alternatives

  • Remove the parameters with duplicate names.
  • Rename the parameters with duplicate names.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Duplicate type %s is redundant

Description

When declaring a complex type, each part of the type must be unique. This means that a type can only be mentioned once.

This constraint is actually easier to explain than to detail: of course, it is important to avoid repeating the same type, yet types may be declared with different case, with or without initial slash, with a local alias, or also with a class_alias().

Then, there is also the possiblity for the type to be part of a composed type, such as bool (which is true|false), or mixed, or iterable, etc.

Only the first redundant type is reported.

Example

<?php

function foo() : A|a|\a|\A {}

function goo() : bool|false {}

?>

Literal Examples

  • Duplicate type a is redundant
  • Duplicate type false is redundant

Alternatives

  • Remove types that are double.
  • Remove the types.

In previous PHP versions, this error message used to be :ref:type-%s-contains-both-iterable-and-array.

Duplicate value in enum %s for cases %s and %s

Description

When an enumeration is backed, either string or int, the values used in the cases must all be distinct. There cannot be any duplicate value. This problem is only reported at execution time, when one of the cases is used.

Example

<?php

enum E: int {
    case A = 1;
    case B = 1;
}

E::A;

?>

Literal Examples

  • Duplicate value in enum E for cases A and B

Alternatives

  • Make sure all the cases are distinct.

Dynamic class names are not allowed in compile-time class constant references

Description

It is not possible to create a constant while using a variable, or similar containers. The expression must be static.

Example

<?php

$foo = 'a';
const A = $foo::C;

?>

Alternatives

  • Use define().
  • Make the value expression static.

elements must be between %d and %d

Description

imagesetstyle() takes an array of color indexes (and, optionally, the special value IMG_COLOR_TRANSPARENT) describing a repeating line style, later used by imageline() when drawing with IMG_COLOR_STYLED. Each element is converted to a C int internally.

Starting in PHP 8.5, GD’s array-accepting functions validate that every element actually fits in a native int instead of silently truncating it. Passing a value outside the int range, such as PHP_INT_MIN on a 64-bit build, now raises a ValueError naming the offending argument, instead of wrapping or misbehaving.

Example

<?php

$im = imagecreatetruecolor(10, 10);

imagesetstyle($im, [gdTransparent, PHP_INT_MIN]);

?>

Literal Examples

  • imagesetstyle(): Argument #2 ($style) elements must be between -2147483648 and 2147483647

Alternatives

  • Only use color indexes and style values that fit within a 32-bit signed integer range (between -2147483648 and 2147483647).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Empty delimiter

Description

The explode() function doesn’t work without a non-empty delimiter. Use an alternative, such as str_split().

Example

<?php

print_r(explode('', 'abc')); // Not possible with an empty delimiter

print_r(str_split(1, 'abc')); 

?>

Alternatives

  • Use str_split() to split the string into individual characters.
  • Access to the different elements.

In more recent PHP versions, this error message is now :ref:cannot-be-empty.

Enabling session.use_trans_sid INI setting is deprecated

Description

session.use_trans_sid is marked for deprecation. When that directive will be removed, the feature will also be removed. Trans ID are session ID that are propagated via GET (in the URL) and POST (in the HTTP headers).

Example

<?php

if (!ini_get('session.use_trans_sid')) {
    die('it is recommended to not use trans id for sessions.');
}

?>

Alternatives

  • Set session.use_trans_sid to off in php.ini.
  • Remove usage of ini_get() with session.use_trans_sid in the code.
  • Remove usage of ini_set() with session.use_trans_sid in the code.

Encoding declaration pragma must be

Description

The declare(encoding = ...) pragma sets the source encoding PHP uses to parse the rest of the script, so, like strict_types, it has to be known before anything else in the file is compiled. It must therefore be the very first statement in the script, exactly like the strict_types declaration.

The full message reads: Encoding declaration pragma must be the very first statement in the script. In practice, this directive only has an effect when the zend.multibyte ini setting is enabled; otherwise it is silently ignored, but the placement rule is still enforced.

Example

<?php

echo 'Hello';

declare(encoding = 'ISO-8859-1');

?>

Literal Examples

  • Encoding declaration pragma must be the very first statement in the script

Alternatives

  • Move the declare(encoding = ...) statement to be the very first statement in the file.
  • Remove any characters or statements placed before the opening <?php tag.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Entry %s does not exist and cannot be deleted

Description

PHP reports failure when trying to remove a file that does not exists in a phar archive. This error message is specific to the Phar::delete method.

Example

<?php

try {
    $phar = new Phar('/tmp/myphar.phar');
    $phar->addFromString('foo.txt', 'hello');
    unset($phar);

    $phar = new Phar('/tmp/myphar.phar');
    $phar->delete('/oops');
} catch (Exception $e) {
    // handle errors
    print $e->getMessage();
}

?>

Literal Examples

  • Entry oops does not exist and cannot be deleted

Alternatives

  • Check if the file exists before removing it.

Enum “%s” not found

Description

This error could not be reproduced so far. Help us by sending us any generating code.

Example


Alternatives

Enum %s cannot implement the Serializable interface

Description

Enumeration cannot be serialized: they are created as needed by the PHP engine, during execution, and they will again at the next execution.

Example

<?php

enum E implements Serializable {
    case A;
}

?>

Literal Examples

  • Enum E cannot implement the Serializable interface

Alternatives

  • Remove the serializable implements.
  • Make this enumeration a class.

Enum %s cannot include magic method %s

Description

Some magic methods are not allowed in an enumeration. __get, __set, __isset, __unset, __construct, __destruct, __sleep, __wakeup, __serialize, __unserialize, __toString, __set_state, __clone and __debugInfo.

This also means that some other magic methods are allowed : __call, __callStatic and __invoke.

Example

<?php

enum E {
    function __get($a) {}
}

?>

Literal Examples

  • Enum e cannot include magic method __get
  • Enum e cannot include magic method __set
  • Enum e cannot include magic method __destruct

Alternatives

  • Remove the magic method from the enumeration.
  • Turn the enumeration into a class.

Enum %s cannot include properties

Description

Enumeration cannot define a property. They can only define constants and methods.

Enum can use a trait, and import several methods. Traits can also define properties, which are mixed with the host. On the other hand, enum cannot define properties: when a trait is used by an enumeration, it should not have any properties. It is also the case for traits of traits.

Example

<?php

enum D {
   private $p = 1;
}

trait T {
   private int $property; 
}

enum E {
    use T;
}

?>

Alternatives

  • Remove the property from the trait.
  • Split the trait in two traits, and include the new trait that has no property.

Enum backing type must be int or string

Description

Backed enumeration have a name and a value for each case. The type of that value is specified next to the enumeration name, and can only by string or int. All other values are forbidden.

Example

<?php

enum E: A {
    case B;
}

?>

Literal Examples

  • Enum backing type must be int or string, A given

Alternatives

  • Remove the type on the enumeration and its cases.
  • Use one of the valid types with the enumeration.

Enum case type %s does not match enum backing type %s

Description

Enumeration may be backed with a scalar type, int or string. When doing so, each case must have a value of that type. And no type juggling happens, so '1' is not an integer, while 1 is not a string. The types must match perfectly one with another.

Example

<?php

enum E : string {
    case A = 1;
}

?>

Alternatives

  • Change the type on the enumeration to fit the value.
  • Change the type on the value to fit the enumeration.
  • Remove types and values.

Enum case value must be compile-time evaluatable

Description

The value of a backed enumeration, string or integer, cannot be build with constant (global or classe). It can only be build with literal values.

This limitation was removed in PHP 8.2.

Example

<?php

enum Foo: string {
    case A = '/' . A;
    case B = '/' . __FILE__;
}

?>

Alternatives

  • Upgrade to PHP 8.2.
  • Replace the constants with literal values.

Enums are not compatible with %s

Description

It is not possible to use an object as backing for the arrayobject class. Enums cases are objects, of the type of the enum. Hence, this is not possible.

Example

<?php

enum Foo {
    case Bar;
}

new ArrayObject(Foo::Bar);

?>

Alternatives

  • Put the value of the case in an array.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Error at offset %zd of %zd

Description

Unserialize() reads a string, and parse it to produce a value: integer, string, array, object… It uses a specific format, and when there isn’t enough information to successfully run the parse, this error message is emitted.

Example

<?php

unserialize("an invalid string");

?>

Alternatives

  • Catch the returned value of the function: when it is null, an error occurred.

exponent cannot have a fractional part

Description

The exponent argument, aka the second, must be an integer value. It might be negative, or even zero, but it cannot be with a decimal separator.

PHP tries to round it, so float values with only zeros after the decimal separator may work.

Example

<?php

echo bcpow('4.2', '3.2', 2); // 74.08

?>

Alternatives

  • Check the argument with is_int().
  • Round the argument to an integer.

Extra data starting at offset %d of %zd bytes

Description

Some extra data were found while processing the serialized string. They are not needed, so they should not be there. It is recommended to investigate why too much data was provided, as it may devolve in a security issue.

There is no way to check the amount of needed data before unserializing the string.

Example

<?php

// 1 3   are too much in this string.
print_r(unserialize('O:1:"a":1:{s:8:"property";s:3:"yes". '1 3';}));

?>

Literal Examples

  • Extra data starting at offset 31 of 3 bytes

Alternatives

  • Catch the warning and review the string after execution.
  • Set up a validation of the incoming string, such as a check sum.

Failed opening required %s (include_path=%s)

Description

This error appears when PHP cannot reach the file for inclusion with require or require_once.

The file may not exist, or the path has a typo and does not point to the actual file. Note that PHP searches for the file once, when the path starts with a leading /. Otherwise, PHP uses the provided path with all the paths provided in the include_path, and stops at the first found file.

The file may be configured no read permissions, making it unavailable for the web server or anyone running the current code.

Parenthesis have no impact on this error.

This error applies only to require and require_once. It does not apply to include and include_once, which reports the same message but proceeds with execution and does not stop with a fatal error. Note that the underlying problem is the same, but the reaction of the inclusions are not the same.

Example

<?php

    require '/not/a/path/to/a/file.inc';

?>

Literal Examples

  • Failed opening required include.php (include_path=‘.:’)

Alternatives

  • Check for typos in the file name.
  • Check for typos in the path name.
  • Check for permissions to reach the file.
  • Check for include_path to provide the correct path prefix.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Failed to create closure from callable: %s

Description

This error message signals that the Closure class could not check the availability of the method to create a closure.

In the illustration code, the class A does not exists. The new Closure is checked at calling time of Closure::fromCallable.

The description of the problem is at the end of the error message, and may vary depending on the situation.

Example

<?php

Closure::fromCallable(['a', 'b']);

?>

Literal Examples

  • Failed to create closure from callable: class a does not exist

Alternatives

  • Pass the array around, and call Closure::fromCallable at the last moment.
  • Create a hard coded closure.

Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times

Description

The insteadof operator resolves a conflict between two or more traits that define a method with the same name: it picks the version to keep, and implicitly excludes that method from the traits listed after insteadof.

Each trait can only be marked as excluded, for a given method, once. Here, B is listed twice in the same insteadof clause for hello(), which is redundant: PHP has nothing more to learn from the second mention, and rejects the declaration outright, rather than silently ignoring the duplicate.

The same error also occurs when the same trait ends up excluded twice for the same method through two separate precedence rules, not just within a single insteadof list.

Example

<?php

trait A {
    public function hello() { echo 'A'; }
}

trait B {
    public function hello() { echo 'B'; }
}

class X {
    use A, B {
        A::hello insteadof B, B;
    }
}

?>

Literal Examples

  • Failed to evaluate a trait precedence (hello). Method of trait B was defined to be excluded multiple times

Alternatives

  • Remove the duplicate trait name from the insteadof list.
  • Check whether the trait is already excluded for that method by another precedence rule.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Failed to open stream from socketpair

Description

This error could not be reproduced so far. Help us by sending us any generating code.

Example


Alternatives

Failed to open stream: Too many open files

Description

This error has two aspects: first, PHP tried to read a file and failed. This is the first part, where files are mentioned as streams. Streams are a more generic version of files: they may be local files, on the file system, or they may be remote, via any kind of protocol, or even, created on the fly by other processes.

The second aspect is a detailed version of the previous: the file failed to be read because the current process has reached the maximum number of possible files to read. This is a system limit, which prevents processes to open an unlimited number of files. Usually, reaching such limit means that the code is opening files carelessly.

To check this limit, run the system command ulimit -n on Linux systems.

Example

<?php

parse_ini_file('/path/to/file.ini');

?>

Alternatives

  • Review the code to limit the number of opened files and sockets.
  • Raise the limit of opened files for the process, by using ulimit -n 10000 (or more, if necessary).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Failed to set memory_limit to %zd bytes. Setting to max_memory_limit instead (currently: %zd bytes)

Description

PHP 8.5 introduced the max_memory_limit INI directive, an administrator-controlled ceiling on how high memory_limit may be raised, whether from php.ini, the command line, or a runtime call to ini_set(). Any attempt, from any of these sources, to set memory_limit above max_memory_limit triggers this warning, and the effective limit is clamped down to max_memory_limit instead.

max_memory_limit defaults to -1 (no ceiling), so it must be configured first, and it is a PHP_INI_SYSTEM directive: it can only be set in php.ini or on the command line, never with ini_set().

To reproduce this message on the command line: php -d max_memory_limit=64M script.php, where script.php is the code above.

Example

<?php

ini_set('memory_limit', '128M');
echo ini_get('memory_limit'), "\n";

?>

Alternatives

  • Lower the requested memory_limit to a value at or below max_memory_limit.
  • Raise max_memory_limit in php.ini if the script genuinely needs more memory.
  • Do not treat the return value of ini_set('memory_limit', ...) as authoritative; re-read it with ini_get('memory_limit') afterwards.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See max_memory_limit

Failed to update the scheme

Description

This is an internal, defensive error. Uri\Rfc3986\Uri::withScheme() asks the bundled uriparser library to replace the scheme component; the library can only report success or a syntax error (surfaced as the-specified-scheme-is-malformed). This exception is thrown for any other, unexpected result code, which should not be reachable from PHP userland — it exists purely as a safety net, not as a condition an application is expected to trigger.

Example


Alternatives

  • This should not occur during normal use; if it does, it indicates a bug in the URI extension or the bundled uriparser library rather than a mistake in your code.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Failed to update the userinfo

Description

This is an internal, defensive error. Uri\Rfc3986\Uri::withUserInfo() asks the bundled uriparser library to replace the userinfo component; the library can only report success, a missing-host condition (cannot-set-a-userinfo-without-having-a-host), or a syntax error (the-specified-userinfo-is-malformed). This exception is thrown for any other, unexpected result code, which should not be reachable from PHP userland — it exists purely as a safety net, not as a condition an application is expected to trigger.

Example


Alternatives

  • This should not occur during normal use; if it does, it indicates a bug in the URI extension or the bundled uriparser library rather than a mistake in your code.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Fetching properties on non-enums in constant expressions is not allowed

Description

Constant expressions are expressions that build the value of a constant. A subset of the features of PHP are available in these expressions.

In particular, objects are allowed, but it is not possible to fetch properties nor call methods. In fact, properties are allowed, but on a specific type of object: enumeration cases.

Example

<?php

class Y {
	public $y = 1;
}

const Y = new Y();

enum Z : string {
	case Z = 'foo';
}

class X {
	const XZ = Z::z->value;
	const X = Y->y;
}

// OK
echo X::XZ;

//Fetching properties on non-enums in constant expressions is not allowed
echo X::X;

?>

Alternatives

  • Do not use properties in constant expressions.

FFI API is restricted by “ffi.enable” configuration directive

Description

FFI is an extension that allows loading C libraries, and building C data structure from PHP. This is a powerful interface, that comes with possible security concerns. Not only FFI must be compiled with PHP, but it also has to be allowed in the php.ini file to be executable.

Since this error message is provided by FFI, it means FFI is installed on the system, but it is not enabled in the php.ini.

Example

<?php
// create FFI object, loading libc and exporting function printf()
$ffi = FFI::cdef(
    "int printf(const char *format, ...);", // this is a regular C declaration
    "libc.so.6");

?>

Alternatives

  • Enable FFI in the php.ini.

Filename cannot be empty

Description

fopen()’s first argument is of type string, though the empty string is not allowed, as it does not lead to any file.

This check prevents using an empty string, or its equivalent as null or false, to access a file.

This error also applies to file_get_contents and file_put_contents(). It doesn’t apply to unlink and rmdir.

Example

<?php

fopen('', 'r');

?>

Alternatives

  • Check the name of the file with empty() before using it with fopen().
  • Check the name of the file against ‘’ (empty string) before using it with fopen().

In more recent PHP versions, this error message is now :ref:path-cannot-be-empty.

filter validation failed: filter %s not satisfied by ‘%s’

Description

PHP 8.5 adds the FILTER_THROW_ON_FAILURE flag, usable with filter_var(), filter_var_array(), filter_input() and filter_input_array(). When it is set and the chosen filter (e.g. FILTER_VALIDATE_EMAIL) rejects the value, a Filter\FilterFailedException is thrown instead of the function returning false, naming both the filter and the offending value.

Example

<?php

filter_var('not-an-email', FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE);

?>

Literal Examples

  • filter validation failed: filter validate_email not satisfied by ‘not-an-email’

Alternatives

  • Wrap the call in a try/catch and handle Filter\FilterFailedException.
  • Do not pass FILTER_THROW_ON_FAILURE if you prefer to check the return value for false instead.

In more recent PHP versions, this error message is now :ref:filter-validation-failed:-not-an-array-(got-%s).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

filter validation failed: not an array (got %s)

Description

The FILTER_REQUIRE_ARRAY flag asks the filter functions to treat the input as an array and filter each element. If the value is not actually an array, this normally makes the function return false. When FILTER_THROW_ON_FAILURE is combined with FILTER_REQUIRE_ARRAY, that same situation instead throws Filter\FilterFailedException naming the type that was received.

Example

<?php

filter_var('a', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY | FILTER_THROW_ON_FAILURE);

?>

Literal Examples

  • filter validation failed: not an array (got string)

Alternatives

  • Pass an array when using FILTER_REQUIRE_ARRAY, or drop that flag if a scalar is expected.
  • Wrap the call in a try/catch and handle Filter\FilterFailedException.

In previous PHP versions, this error message used to be :ref:filter-validation-failed:-filter-%s-not-satisfied-by-%s. In more recent PHP versions, this error message is now :ref:filter-validation-failed:-object-of-type-%s-has-no-__tostring()-method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

filter validation failed: object of type %s has no __toString() method

Description

The filter functions convert their input to a string before applying a filter. If the input is an object without a __toString() method, that conversion is impossible; normally the function returns false (or null/the default option, depending on the flags used). With FILTER_THROW_ON_FAILURE set, this instead throws Filter\FilterFailedException naming the offending class.

Example

<?php

filter_var(new stdClass(), FILTER_VALIDATE_EMAIL, FILTER_THROW_ON_FAILURE);

?>

Literal Examples

  • filter validation failed: object of type stdClass has no __toString() method

Alternatives

  • Only pass objects that implement __toString(), or convert the value to a string yourself first.
  • Wrap the call in a try/catch and handle Filter\FilterFailedException.

In previous PHP versions, this error message used to be :ref:filter-validation-failed:-not-an-array-(got-%s).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

foreach() argument must be of type array|object

Description

foreach() works on arrays or objects.

For the arrays, all the elements of the array are read.

For the objects, it is either the public properties, read like an array; or the object has the Iterator interface: then, there is a list of specific methods to implements, which control how the object is traversed; the object may be a generator, which is a method that uses the yield keyword; finally, the object may be a PHP native iterator, or a child of them.

Then, any other type is forbidden to be used with foreach(). This means all scalars elements, including string, integer and null.

Example

<?php

    $source = null;
    foreach($source as $x) { }

?>

Alternatives

  • Check that the source of the foreach can be used with is_iterable().

In previous PHP versions, this error message used to be :ref:invalid-argument-supplied-for-foreach().

func_get_arg() cannot be called from the global scope

Description

func_get_arg() returns the list of arguments used when calling a function or method. As such, it must be inside a function to be useful.

Example

<?php

func_get_arg(0);

?>

Alternatives

  • Remove func_get_arg() calls from the global space (outside any function).
  • Move the func_get_arg() calls inside a function.

func_get_args() cannot be called from the global scope

Description

func_get_args() returns the list of arguments used when calling a function or method. As such, it must be inside a function to be useful.

Example

<?php

func_get_args();

?>

Alternatives

  • Remove func_get_args() calls from the global space (outside any function).
  • Move the func_get_args() calls inside a function.

func_num_args() must be called from a function context

Description

func_num_arg() returns the number of arguments used when calling a function or method. As such, it must be inside a function to be useful.

Example

<?php

func_num_args();

?>

Alternatives

  • Remove func_num_args() calls from the global space (outside any function).
  • Move the func_num_args() calls inside a function.

Function %pS() does not exist

Description

The ReflectionFunction constructor requires the name of an existing user-defined or internal function. When the given name does not match any declared function, the Reflection API cannot build the requested introspection object and throws a ReflectionException instead.

Example

<?php

$reflection = new ReflectionFunction('does_not_exist');

?>

Literal Examples

  • Function does_not_exist() does not exist

Alternatives

  • Check the function name for typos.
  • Make sure any file declaring the function has been included before creating the ReflectionFunction.
  • Use function_exists() to check the function is available before reflecting on it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Function %s() is deprecated%S

Description

PHP native functions get deprecated, before being removed. This message is here to help with refactoring the code to more modern syntax, and get ready for upcoming versions.

Example

<?php

// One of the deprecated functions
echo strftime(1);

?>

Literal Examples

  • Function strftime() is deprecated since 8.1, use IntlDateFormatter::format() instead

Alternatives

  • Use the suggestion from the error message.

Function libxml_disable_entity_loader() is deprecated since 8.0, as external entity loading is disabled by default

Description

This warning signals that PHP is not using this function anymore: the features of loading external entities has been disabled, for security purposes: loading entities from a remote server without checking them was a serious vulnerability.

The deprecation warning warns the user that this feature is already inactive.

Example

<?php

libxml_disable_entity_loader(true);

?>

Alternatives

  • Remove the call to libxml_disable_entity_loader().

Function name must be a string

Description

When calling a function dynamically, the name of the function, in the $method variable, must be a string, and the function must exist.

Some other scalars, such as integer, might be used as function name, although it will fail.

Example

<?php

$method = new stdClass;
$method();

?>

Alternatives

  • Only use string names for dynamic call to functions.
  • Cast the variable to string before using it.

In more recent PHP versions, this error message is now :ref:object-of-type-%s-is-not-callable.

Generated salt too short

Description

password_hash() creates a random salt for each hash. This error is thrown when the salt that was generated is shorter than the length the hashing algorithm needs, so the hash cannot be built.

Application code cannot fix this directly, as the salt is created inside PHP. It points to a problem with the random data or with the PHP build, and it is rare.

Example


Literal Examples

  • Generated salt too short

Alternatives

  • Check that random_bytes() works on the system, for example by calling random_bytes(16) in a small script.
  • Check the PHP build, and reinstall PHP if it is a custom or damaged build.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Generator return type must be a supertype of Generator

Description

When a method or a function uses a yield keyword, it becomes a generator. It also means that the return type of this method must be Generator, or any other of its supertypes: Traversable, Iterator, Generator or iterable.

There is no way to set a type on the yielded values: only on the returned values. In this case, it will be a Generator. Strangely, any value in a return expression is also valid.

It may also be simply removed, and left implicit.

Example

<?php

function foo() : X {
	yield 1;
	
	return true;
}

?>

Alternatives

  • Use the return type Generator.

Generators cannot return values using “return”

Description

In PHP 5.x, generators were not allowed to have return values. This feature was added in PHP 7.0, and, after running the full course, generator deliver their return value when calling the getReturn method.

Example

<?php

function foo() {
    yield 1;
    
    return 2;
}

?>

Alternatives

  • Upgrade to PHP 7.0 or more recent.
  • Use a global variable to export data from the method.

Get hook of backed property %s::%s with set hook may not return by reference

Description

When a property is a virtual property, the get hook cannot return a reference.

Example

<?php

class A {
    public $prop;
}

class B extends A {
    private $_prop;
    public $prop {
        &get => $this->_prop;
        set { $this->_prop = $value; }
    }
}

?>

Literal Examples

  • Get hook of backed property B::$prop with set hook may not return by reference

Alternatives

  • Make the virtual property a concrete one.
  • Remove the reference.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

get hook of property %s::$%s must not have a parameter list

Description

The get hook property cannot be specified with a parameter list: not with a parameter, nor even with the empty parenthesis.

Example

<?php

class X {
    private int $p {
        get($a) => 1;
    }

    private int $q {
        get() => 1;
    }
}


?>

Literal Examples

  • get hook of property X::$p must not have a parameter list

Alternatives

  • Remove the parenthesis that follows the get keyword, and their content.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

get_called_class() must be called from within a class

Description

get_called_class() returns the name of the current class. It emits an error when it cannot find the current class.

get_called_class() can only be called from within a class, trait or enumeration. It may be called from a static closure, as long as the closure is created inside a class.

Example

<?php

get_called_class();

?>

Alternatives

  • Use the magic constant CLASS.
  • Use the function inside a class, enumeration or trait.

get_defined_functions(): Setting $exclude_disabled to false has no effect

Description

The first (and only) parameter of the PHP native function get_defined_functions() is deprecated since PHP 8.0 and will disappear in PHP 9.

Example

<?php

$list = get_defined_functions(false); 

?>

Alternatives

  • Remove all parameter usage when calling get_defined_functions(), and fetch the list of disabled functions another way.
  • Check that the parameter is never false before usage.

get_defined_functions(): The $exclude_disabled parameter has no effect since PHP 8.0

Description

The $exclude_disabled parameter of the function get_defined_functions() function is unused since PHP 8.0. In PHP 7.0, it used to remove the disabled function from the result of this function.

Example

<?php

    print_r(get_defined_functions(false));

?>

Alternatives

  • Remove the parameter from any call to get_defined_functions().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See get_defined_functions

Handling Base64 via mbstring is deprecated; use base64_encode/base64_decode instead

Description

Since PHP 8.2, several encodings were dropped from mbstring, including base64.

This is a deprecation, so the feature is available until PHP 9.

Example

<?php

mb_convert_encoding('foo', 'base64');

?>

Alternatives

  • It is recommended to use the base64_encode() and base64_decode() functions to do this.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_convert_encoding

Handling HTML entities via mbstring is deprecated; use htmlspecialchars, htmlentities, or mb_encode_numericentity/mb_decode_numericentity instead

Description

Since PHP 8.2, several pseudo-encodings were dropped from mbstring, including HTML-ENTITIES, which converted characters to and from their HTML numeric/named entity representation.

This functionality overlapped with dedicated, better-maintained functions, and its removal simplifies the mbstring encoding conversion tables. It remains usable until PHP 9, when it will be removed entirely.

Example

<?php

mb_convert_encoding('foo', 'HTML-ENTITIES');

?>

Alternatives

  • Use htmlspecialchars() or htmlentities() to encode text as HTML entities.
  • Use mb_encode_numericentity()/mb_decode_numericentity() for numeric entity conversion.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_convert_encoding

Handling HTML entities via mbstring is deprecated; use htmlspecialchars, htmlentities, or mb_encode_numericentity/mb_decode_numericentity

Description

Since PHP 8.2, several encodings were dropped from mbstring, including html.

This is a deprecation, so the feature is available until PHP 9.

Example

<?php

mb_convert_encoding('foo', 'html');

?>

Alternatives

  • It is recommended to use the htmlspecialchars(), htmlentities(), mb_encode_numericentity(), mb_decode_numericentity() functions to do this.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_convert_encoding

Handling QPrint via mbstring is deprecated; use quoted_printable_encode/quoted_printable_decode instead

Description

Since PHP 8.2, several pseudo-encodings were dropped from mbstring, including qprint (Quoted-Printable), a text encoding that represents non-ASCII bytes using =XX sequences.

This functionality overlapped with the dedicated quoted_printable_encode()/quoted_printable_decode() functions provided by the standard extension. It remains usable until PHP 9, when it will be removed entirely.

Example

<?php

mb_convert_encoding('foo', 'qprint');

?>

Alternatives

  • Use quoted_printable_encode() and quoted_printable_decode() instead of mb_convert_encoding() with the qprint encoding.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_convert_encoding

Handling QPrint via mbstring is deprecated; use quoted_printable_encode/quoted_printable_decode

Description

Since PHP 8.2, several encodings were dropped from mbstring, including QPrint.

This is a deprecation, so the feature is available until PHP 9.

Example

<?php

mb_convert_encoding('foo', 'qprint');

?>

Alternatives

  • It is recommended to use the quoted_printable_encode() and quoted_printable_decode() functions to do this.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_convert_encoding

Handling Uuencode via mbstring is deprecated; use convert_uuencode/convert_uudecode instead

Description

Since PHP 8.2, several encodings were dropped from mbstring, including uuencode.

This is a deprecation, so the feature is available until PHP 9.

Example

<?php

mb_convert_encoding('foo', 'uuencode');

?>

Alternatives

  • It is recommended to use the convert_uuencode() and convert_uudecode() functions to do this.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_convert_encoding

has #[\Override] attribute, but no matching parent method exists

Description

Override is a PHP attribute, that checks if a method is actually overriding the same method from a parent class. This means that there should be a method in one of the parent class, that have the same name.

When no such method is found, it signals that the method with the attribute is now orphaned. It should be renamed, to fit another method.

The error is emitted when a method has the Override but no such method exists in the parent; it is also emitted when Override is used in a class or an interface that has no parent. No error is emitted on traits or enums.

This error is a compile time error, when PHP can solve it at compile time: this means both the class with the Override attribute, and the parent class is available at compile time. It is also an execution time error, when the Override is set in a method in a trait.

Example

<?php

#[Attribute]
class X {}

class Y extends X {
	#[Override]
	function foo() {}
}

?>

Alternatives

  • Remove the Override attribute.
  • Rename the current method with the name of a method in the parents.
  • Remove the method.
  • Rename one of the parent method to use the name of the current method.

has a malformed IPv6 address, closing square bracket missing

Description

SNMP::__construct() accepts an IPv6 $hostname wrapped in square brackets, such as [::1] or [::1]:1161 for a non-default port. The closing ] is what tells the parser where the address ends and an optional :port suffix begins.

If the hostname starts with [ but never contains a matching ], the address cannot be parsed. As of PHP 8.6, this now throws a ValueError instead of emitting a warning and leaving the session half-constructed.

Example

<?php

$snmp = new SNMP(SNMP::VERSION_2c, '[::1', 'public');

?>

Literal Examples

  • SNMP::__construct(): Argument #2 ($hostname) has a malformed IPv6 address, closing square bracket missing

Alternatives

  • Make sure a bracketed IPv6 $hostname is properly closed, e.g. [::1] or [::1]:1161.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, this emitted an E_WARNING (“Malformed IPv6 address, closing square bracket missing”) and left the SNMP object without a usable session, instead of throwing.](Previously, this emitted an E_WARNING (“Malformed IPv6 address, closing square bracket missing”) and left the SNMP object without a usable session, instead of throwing.)

Hooked properties cannot be readonly

Description

The readonly keyword is not allowed on hooked properties. On the other hand, it is possible to emulate that feature, by writing the set method.

Example

<?php

class X {
    public readonly string $x {
    	get => $this->x;
    	
    	set { if (!isset($this->x)) $this->x = $value;}
    }
}

?>

Alternatives

  • Use the set hook to emulate readonly.
  • Omit the readonly keyword.
  • Remove the property hooks from the property definition.

Illegal class name

Description

Illegal class name is a compile-time error when the type of a value, used for a class is not valid.

The expressions that use classes are the following : static method call, static property call, static constant call, and static class ($a::class).

The valid types are strings, static class (A::class), identifiers (such as A or \A), method calls (foo()) that returns one of the previous types or data containers holding an object or a class name as a string. On the other hand, boolean, null, integers, float, array() are invalid; some strings are not valid, such as ‘4foo’, though PHP only detects these are execution time, with a different error message.

This kind of error is very rare, as it prevents the code to run.

Example

<?php

array()::t;
(2)::$t;
(true)::t();

//Illegal classname, as integer cannot be a classname
strlen($string)::$property;

// This is valid until execution, where class 4f cannot be found
('4f')::$t;

?>

Alternatives

  • Do not use invalid types values to access a class.

Illegal function name

Description

This error messages appears when there is an attempt to create a closure from a function, whose name is not a valid function. Numbers, such as float and integers, are not valid function name, and yield this error. Negative numbers, and other types yield a distinct error.

Example

<?php

const Closure = (0)(...);

var_dump(Closure);

?>

Alternatives

  • Use a string, instead of a number. Check that the string is a valid name for a function or a static method.
  • Ensures that the name is a static expression, and that each element may be resolved at compile time.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Illegal method name

Description

PHP 8.5 allows first-class callable syntax ((...)) to be used inside a constant expression, so that a static method call can be turned into a Closure at compile time. To build that closure, the compiler needs the method name as a string that it can resolve at compile time.

Here, the braced expression {0} is a compile-time constant, but it is an integer, not a string, so it cannot be used as a method name. PHP reports this as an illegal method name.

This differs from ‘Cannot use dynamic method name in constant expression’, which is reported when the braced expression cannot be resolved to a constant value at all (for example, because it depends on a variable or is a non-scalar value such as an array).

Example

<?php

class X {
    public static function foo() { return 1; }
}

const C = X::{0}(...);

var_dump(C);

?>

Alternatives

  • Use a string, instead of a number or another scalar, for the method name.
  • Ensure the method name is a literal string, or an expression that PHP can resolve to one at compile time.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See constantExpressionMethodNameResolution85

Illegal offset type in isset or empty

Description

PHP only uses integers and strings as array index. While certain other types may be converted silently to those types, as null or boolean, objects and arrays yield an illegal type for index.

This error is is specific to isset and empty: these functions are usually very silent, yet an dedicated error message was created for the type check.

This error is reported at compile time when PHP can detect the type then, otherwise, it is reported at execution time.

Example

<?php

$array = [1];

var_dump(isset($array[[]]));

?>

Alternatives

  • Convert these types into a string or a integer first.
  • Cast these types into a string or a integer first.

Illegal offset type in unset

Description

PHP only uses integers and strings as array index. While certain other types may be converted silently to those types, as null or boolean, objects and arrays yield an illegal type for index.

This error is is specific to unset: this function is usually very silent, yet an dedicated error message was created for the type check.

This error is reported at compile time when PHP can detect the type then, otherwise, it is reported at execution time.

Example

<?php

$array = [1];

unset($array[[]]);

?>

Alternatives

  • Convert these types into a string or a integer first.
  • Cast these types into a string or a integer first.

Illegal offset type

Description

PHP only uses integers and strings as array index. While certain other types may be converted silently to those types, as null or boolean, objects and arrays yield an illegal type for index.

This error is reported at compile time when PHP can detect the type then, otherwise, it is reported at execution time.

Example

<?php

$a = new Stdclass;

$array = [$a => 2];

$array[$a] = 1;

$array[$array] = 3;

?>

Alternatives

  • Convert these types into a string or a integer first.
  • Cast these types into a string or a integer first.

illegal string offset

Description

String shall use the array syntax, with the square brackets. Then, the index in that syntax must be an integer, or must be cast to integer.

When the index cannot be converted to an integer, this warning is displayed. PHP proceeds to cast the value to integer, and use it. It will often be 0, but not always.

An extended error also appear if the result of the conversion is larger than the length of the string.

Example

<?php
  var_dump(foobar[4foo]);
  // displays 'a' + a warning

  var_dump(foobar[-4foo]);
  // displays 'o' + a warning
?>

Alternatives

  • Use a cast operator to make the conversion explicit.
  • Check the type of the index to be integer before using it.
  • Use substr() to access a specific offset.

Implicit conversion from float %.*H to int loses precision

Description

This warning is emitted when a float is passed to a typed value that requires an integer. The float is truncated, not rounded, to an integer, and passed.

This becomes a Fatal error when strict_types is actived.

The float might be a valid integer, when it has no decimal part: then, no error is emitted.

Example

<?php

function foo(int $a): int {
    // At return time
    return $a - 0.5;
}

// At call time
foo(1.1);

?>

Literal Examples

  • Implicit conversion from float 1.1 to int loses precision
  • Implicit conversion from float 0.5 to int loses precision

Alternatives

  • Cast the float to integer before using it with a typed resource.
  • Round the float to integer before using it with a typed resource.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See implicitConversionToInt

Implicit conversion from float-string “%s” to int loses precision

Description

Bitshift operators and bitwise operators work on integers, not on floats. When a string is provided, it may be converted to integer or float: in the second case, the deprecation warning is emitted.

The warning is not emitted when the conversion lands on an integer.

Example

<?php

// Extract from php-src/Zend/tests/float_to_int/warnings_string_float_literals.phpt
$var = '1.5'|3;
$var = '1.5'&3;
$var = '1.5'^3;
$var = '1.5' << 3;
$var = '1.5' >> 3;
$var = 3 << '1.5';
$var = 3 >> '1.5';

//OK : PHP is smart enough to round this to integer
((1 / 35) * 35) | 3;

//Implicit conversion from float 0.9999999999999999 to int loses precision 
//The rounding is not sufficient 
((1 / 35) * 7 * 5 ) | 3;

// valid, conversion gives an integer
$var = '14.00000000'|3;

// still valid, conversion does not handle 0.0000000000000001 precision
$var = '13.0000000000000001'|3;

?>

Literal Examples

  • Implicit conversion from float-string “1.5” to int loses precision
  • Implicit conversion from float-string “0.9999999999999999” to int loses precision

Alternatives

  • Cast the string to integer before using it with bitshift or bitwise operators.
  • Round the string to integer before using it with bitshift or bitwise operators.
  • Simplify the expressions before using it with bitshift or bitwise operators.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See implicitConversionToInt

Implicit conversion from float-string “%s” to int loses precision

Description

In cases where integers are required, PHP applies a type cast and convert floats and strings into integers. In many cases, that conversion is eponymous, with 1.0 (float) or ‘10’ being obviously converted to their integer equivalent.

When the conversion is not flawless, in particular when there is a significant decimal part in the float number, this conversion is deleting a part of the value. This message is meant to raise awareness about it.

Situations where this may happens are varied : index in arrays or strings, operators that works on integers, such as bitshift; logical and bitwise operators, etc.

This is a variation of the error ‘A non-numeric value encountered’, where the value could not be converted sanely to an integer.

Example

<?php

$a = [1.23 => 3];

?>

Literal Examples

  • Implicit conversion from float-string “1.23” to int loses

Alternatives

  • Explicitly cast the value to integer.
  • Check if the value is an integer before usage.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See implicitConversionToInt

Implicit conversion from float-string "%s" to int loses precision

Description

In weak typing mode (the default), a string argument passed where an int parameter is declared is coerced automatically, provided the string is numeric. When that string looks like a float rather than an integer – e.g. '1.5' – PHP still coerces it, by first converting it to a float and then truncating that float to an int, silently discarding the fractional part.

As of PHP 8.1, this specific case – a float-shaped string being coerced down to an int and losing precision in the process – emits a deprecation notice. It is a sibling of the same underlying helper that also fires for float array keys and for bitwise/bitshift operators applied to float-like strings, which are documented separately since they are different call sites in practice.

Example

<?php

function double(int $x) {
    return $x * 2;
}

// Weak typing lets a numeric string be passed where an int is
// declared, but '1.5' cannot become an int without losing the .5.
var_dump(double('1.5'));

?>

Literal Examples

  • Implicit conversion from float-string “1.5” to int loses precision

Alternatives

  • Round or cast the value explicitly before calling the function: double((int) round((float) $x)).
  • Declare the parameter as int|float and handle both cases inside the function.
  • Validate the input is an integer-shaped string (e.g. with ctype_digit()) before relying on implicit coercion.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See implicitConversionToInt

Inconsistent insteadof definition. The method %s is to be used from %s

Description

The insteadof rule picks, for a given method name, the trait it should be taken from, and implicitly excludes that same method from every trait listed after insteadof.

Here, A::foo insteadof A, B says both that foo should come from A, and that A’s own foo should be excluded, which is a direct contradiction. PHP’s full message continues with , but %s is also on the exclude list naming the trait found in both places – a part not captured in this templated entry, which only records the first sentence.

Note that listing a trait that is not otherwise involved in the conflict after insteadof is fine and does not raise this error; it is specifically excluding the trait the method is kept from that is inconsistent.

Example

<?php

trait A {
    public function foo() {}
}

trait B {
    public function foo() {}
}

class C {
    use A, B {
        A::foo insteadof A, B;
    }
}

?>

Literal Examples

  • Inconsistent insteadof definition. The method foo is to be used from A

Alternatives

  • Remove the trait providing the winning method from its own exclude list, keeping only the other conflicting traits after insteadof.
  • Rewrite the rule as A::foo insteadof B; if only B’s foo should be excluded.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Increment on non-alphanumeric string is deprecated

Description

Incrementing a string in a variable is an old darling PHP feature. As long as the last character is an ascii letter, it is incremented to the next ascii value, or wrap to a.

This feature is deprecated since PHP 8.3, and it is replaced by a call to str_increment() and str_decrement() (the last one is a new feature).

Example

<?php

// Increment on non-alphanumeric string is deprecated! (in PHP 8.5)
$a = 'aaa';
echo ++$a;

// Increment on non-alphanumeric string is deprecated
$a = 'aaa!';
echo ++$a;

?>

Alternatives

  • Use str_increment().
  • Change the generating system entirely.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See incrementNonAlphanumeric

Increment on non-numeric string is deprecated, use str_increment() instead

Description

PHP 8.3 introduced str_increment() and str_decrement(), which update strings by changing the last character’s ascii code. It mirrors a famous PHP easter egg, where a string may be incremented with the ++ operator.

In PHP 8.5, this feature is deprecated, and a warning is emitted. There is no deprecation warning for decrementing, as the feature was not implemented on strings.

Example

<?php

    $string = 'aa';
    ++$string;

    echo $string;

?>

Alternatives

  • Use str_increment(), instead of ++ on string variables.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See incrementNonAlphanumeric

Increment on type bool has no effect, this will change in the next major version of PHP

Description

Post increment on a boolean leaves the value unchanged. While PHP updates strings, integers, floats with the post-increment operator, booleans are immune.

Until PHP 8.3, it was silently done. In PHP 8.3, it raises a deprecation warning, and it will be removed in PHP 9.0.

Post increment, pre increment, as well as increment and decrement are affected by that warning. str_increment() and str_decrement() refuses to use boolean, due to type.

Example

<?php

$a = true;
$a++;
// $a = true

$b = false;
--$b;
// $b = false

?>

Alternatives

  • Avoid initializing variables with booleans before incrementing them.
  • In case of doubt, check the type before the increment.

Index invalid or out of range

Description

This error message is returned by the SplFixedArray object, when trying to access indices outside the validity interval. A SplFixedArray has a limited number of elements, set at the beginiing, or updated laster with setSize().

On a regular array, accessing an undefined index is a warning, not a fatal error.

A different message is emited when the index is not an integer.

Example

<?php

$object = new SplFixedArray(3);

$object[1] = 3;
echo $object[1]; // OK
echo $object[0]; // OK, returns null

echo $object[-1];
//Fatal error: Uncaught RuntimeException: Index invalid or out of range

?>

Alternatives

  • Check the size of the array before accessing one of the index.
  • Check that the index is zero or more.
  • Use a regular array.

Indirect modification of %s::$%s is not allowed

Description

While it is possible to create references on object’s properties, it is not possible to do so on a property with a hook. The property hook is returned by value, by default.

Example

<?php

class X {
    public $byRef {
        get {
            $x = 42;
            return $x;
        }
    }
}

$x = new X();
$y = &$x->byRef;

?>

Literal Examples

  • Indirect modification of X::$byRef is not allowed

Alternatives

  • Add & before the get hook.
  • Make the property a normal property, without hooks.
  • Avoid using a reference on a property hook.

Indirect modification of overloaded element of %s has no effect

Description

The variable $object is an object. Since it implements the ArrayAccess interface, it may also use the array syntax, for example with the brackets and index.

While the syntax makes $object looks like an array, not all operations are available. It is possible to get an index’s value, or to give it a new value; but it is not possible to use the increment or decrement operators : those are both a get and a set, and this is not supported by the ArrayAccess interface.

Here, the notion of ‘overloaded’ applies to the object properties: they are not data containers, as usual, but replaced (overloaded) with method calls.

There are different variations of that situation : for example, an append on the value at an index is not possible either. In fact, the interface returns a value (not a reference), and the append applies to a value, that is not linked the original array.

Besides the ArrayAccess, there are several native PHP classes that triggers these warning: ArrayObject, ArrayIterator, PDORow or ArrayAccessImpl.

Example

<?php
class ObjectOne implements ArrayAccess {
    function offsetGet($index): mixed {
        echo __METHOD__ . "($index)\n";
        return 2;
    }

    function offsetExists($index): bool { return true; /**/ }
    function offsetSet($index, $newval): void { /**/ }
    function offsetUnset($index): void { /**/ }
}

$object = new ObjectOne;

$object[2]++;
$object[2][3] = 2;

?>

Literal Examples

  • Indirect modification of overloaded element of $object has no effect

Alternatives

  • Use an actual array to handle those edge cases.
  • Write the ObjectOne class to handle these operation with a method call.

Indirect modification of overloaded property %s::$%s has no effect

Description

The variable $object is an object. Since it implements the __get magic method, any property is available.

While the syntax makes $object->something looks like a actual property and an array, not all operations are available. It is possible to get any property’s value, or to give it a new value; but it is not possible to use the append operator : this is not supported by the magic method.

There are different variations of that situation : for example, an increment or decrement on the value on a property is not possible either.

There is no call that will relay to the magic method that this property is being appended or incremented.

Example

<?php
class OneObject {
    function __get($var) { }
}
$object = new OneObject;
$object->something[] = 'bar';
?>

Literal Examples

  • Indirect modification of overloaded property OneObject::$something has no effect

Alternatives

  • Use an actual data container to represent a property.

Input number is larger than PHP_INT_MAX, precision has been lost in conversion

Description

bindec(), octdec(), hexdec() and base_convert() all share the same internal conversion routine, which accumulates the result in a zend_long for as long as it fits, then switches to a double once the value would overflow. Once that switch happens, the number is only an approximation: a double only has 53 bits of mantissa, so digits beyond that are rounded away.

PHP 8.6 emits a notice the moment this switch occurs, to make the precision loss visible instead of silently returning an inexact float.

Example

<?php

echo hexdec('FFFFFFFFFFFFFFFF');

?>

Literal Examples

  • Input number is larger than PHP_INT_MAX, precision has been lost in conversion

Alternatives

  • Use the GMP or BCMath extensions to convert arbitrarily large numbers between bases without losing precision.
  • Validate the input length against the base before conversion, so it is guaranteed to fit in a native integer.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, bindec(), octdec(), hexdec() and base_convert() silently returned a float once the number no longer fit in an integer, without any indication that precision had been lost. As of PHP 8.6, this now emits an E_NOTICE.](Previously, bindec(), octdec(), hexdec() and base_convert() silently returned a float once the number no longer fit in an integer, without any indication that precision had been lost. As of PHP 8.6, this now emits an E_NOTICE.)

instanceof expects an object instance, constant given

Description

Until PHP 7.3, PHP required an object as the left operand of instanceof. In recent versions, PHP does not emit an error anymore, and returns null.

Although the function reports a constant problem, the error is reported with literal values, and not with constants.

Constants were allowed to receive objects in PHP 8.1.

Example

<?php

null instanceof A::class;

?>

Alternatives

  • Upgrade to PHP 7.3 or more recent.
  • Chech the left operand with is_object(), before using instanceof.

Instantiation of class Closure is not allowed

Description

The Closure class is a PHP native class, which cannot be directly instantiated. It must be created with other syntaxes, such as the closure syntax, function () {};, first class callable foo(...), or arrow functions fn () => 1;.

Example

<?php

new Closure();

?>

Alternatives

  • Use the closure syntax.
  • Use the arrow function syntax.
  • Use the first class callable syntax.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Instantiation of mysqli_stmt without providing the $query parameter is deprecated

Description

mysqli_stmt’s constructor accepts an optional $query string, which, when given, prepares the statement immediately. Omitting it produces an object that is not fully initialized: most of its properties and methods throw until prepare() is called explicitly, which is a confusing two-step state for a class whose entire purpose is to represent a prepared statement. PHP 8.6 deprecates constructing (or calling mysqli_stmt_init() / mysqli::stmt_init()) without a query.

Example

<?php

$link = mysqli_connect('localhost', 'my_user', 'my_password', 'world');

$stmt = new mysqli_stmt($link);

?>

Alternatives

  • Pass the SQL statement directly to the constructor: new mysqli_stmt($link, $query), or use mysqli_prepare() / $mysqli->prepare().
  • If you need the two-step flow, call $stmt->prepare($query) immediately after construction to avoid using the object while uninitialized.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Interface “%s” not found

Description

This error message is reported when the interface could not be loaded, or when the name of the class is invalid.

Example

<?php

// '4f' is not a valid name for an interface
('4f')::c;

// it is not possible to name a class 'interface'
('interface')::c;

?>

Literal Examples

  • Interface “4f” not found
  • Interface “interface” not found

Alternatives

  • Check spelling and namespace for that interface.
  • Create the required interface.
  • Check if the interface is defined in an extension, and the extension is included in the current PHP engine.
  • Check if the interface is defined in a dependency, and the dependency is included in the current composer.json.
  • Do not use static, parent or self in a string to call a method statically.

In previous PHP versions, this error message used to be :ref:interface-%s-cannot-implement-itself.

Interface %s cannot contain non abstract method %s()

Description

In an interface, there can only be methods signature, and no method body. Aka, this means only the semi-colon after the method signature, et no body block.

Methods in an interface are considered abstract by default. There is no need to add such explicit option, nor is it even legal to use it there.

Hence, in an interface, there are only abstract methods: methods without a body. The abstract keyword is implicit in an interface; When the interface is partially implemented by a class, the remaining methods must be declared abstract in that class.

If some methods have to be made concrete (aka, not abstract), it is possible to create an abstract class, with a mix of abstract and concrete methods, which can then be extended by the target class.

Example

<?php

interface I {
	function foo() {}
	
	function bar() ;
}

abstract class CI  {
	function foo() {}
	
	abstract function bar() ;
}

?>

Literal Examples

  • Interface I cannot contain non abstract method foo()

Alternatives

  • Remove all bodies in an interface’s method.
  • Turn the interface into an abstract class.
  • Move the concrete class to a trait, and use the trait, along with the interface.

Interface %s cannot extend class %s

Description

An interface must extends another interface. It cannot extends a class, nor a trait, nor an enum.

Also, a class cannot extends an interface: it must implement it.

Example

<?php

class X {}

interface I extends X {} 

?>

Literal Examples

  • Interface I cannot extend class C

Alternatives

  • Turn the original class into an interface.
  • Make the original interface into an class.
  • Split the class into a class and an interface, and extends the latter.

Interface %s cannot implement itself

Description

An interface can extend another interface, to expand its list of methods. It cannot extends itself, as it is useless.

Example

<?php

interface I extends I {}

?>

Literal Examples

  • Interface I cannot implement itself

Alternatives

  • Extend another interface.
  • Do not extend the current interface.

In more recent PHP versions, this error message is now :ref:interface-"%s"-not-found.

Interface method %s::%s() must not be final

Description

A method in an interface cannot be final, as it has to be implemented: it is actually abstract. The same method, in the implementing class, may be final.

Example

<?php

interface X {
    final function foo();
}

?>

Literal Examples

  • Interface method X::foo() must not be final

Alternatives

  • Remove the final option in the interface, add it to any implementing class, or its children.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Interfaces may not include properties

Description

Interfaces can define methods and constants, but they can’t define properties. Actually, they can only define properties with a property hook, as the property hooks are methods.

Example

<?php

interface I {
	private $property;
}

?>

Alternatives

  • Upgrade PHP version to 8.4.
  • Turn the interface in an abstract class.
  • Turn the interface in a trait.
  • Add a property hook to a property.

In previous PHP versions, this error message used to be :ref:interfaces-may-only-include-hooked-properties.

Interfaces may only include hooked properties

Description

PHP 8.4 introduced the support for properties in interfaces. Although, the properties must have a property hook, aka one associated method that deals with get and set operations on that property.

Example

<?php

interface I {
    public $property;

    public $propertyWithHook {
    	// This is an abstract property
    	get;
    };

}
?>

Alternatives

  • Add an identity hook, such as get => $this->property = $value;, which is the default behavior.
  • Turn the interface into an abstract class.
  • Turn the interface into a trait.

In more recent PHP versions, this error message is now :ref:interfaces-may-not-include-properties.

Internal function %s%s%s() does not accept named variadic arguments

Description

Internal (C-implemented) functions with a variadic parameter, such as array_merge()’s ...$arrays, only ever have a single name for that parameter. When a call spreads an array with string keys into such a function using ..., PHP tries to match each key against a parameter name, and every key besides the one matching the variadic parameter’s own name is rejected, since there is no other named slot for it to bind to.

This restriction is specific to internal functions: user-defined variadic functions accept arbitrary named arguments into their variadic parameter without complaint.

Example

<?php

$parts = ['x' => [1], 'y' => [2]];

array_merge(...$parts);

?>

Literal Examples

  • Internal function array_merge() does not accept named variadic arguments

Alternatives

  • Apply array_values() to the array before spreading it into the internal function, so its keys are reset to plain integers and no longer interpreted as parameter names.

In previous PHP versions, this error message used to be :ref:array_merge()-does-not-accept-unknown-named-parameters.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, the same ArgumentCountError was thrown, but worded “%s%s%s() does not accept unknown named parameters” (e.g. “array_merge() does not accept unknown named parameters”), without the “Internal function” prefix and without naming variadic arguments specifically as the cause.](Prior to PHP 8.6, the same ArgumentCountError was thrown, but worded “%s%s%s() does not accept unknown named parameters” (e.g. “array_merge() does not accept unknown named parameters”), without the “Internal function” prefix and without naming variadic arguments specifically as the cause.)

IntlListFormatter object is already constructed

Description

IntlListFormatter, added in PHP 8.5, wraps ICU’s list formatter to render lists such as "a, b, and c" according to locale rules. Like other intl classes, its constructor guards against being run twice on the same object: the first successful call allocates the underlying ICU formatter, and a second call would leak that resource and leave the object in an inconsistent state.

Calling __construct() explicitly a second time – directly, or indirectly through code that re-runs construction on an already built instance – throws this error.

Example

<?php

$formatter = new IntlListFormatter('en_US');

// Calling the constructor a second time on the same instance
$formatter->__construct('fr_FR');

?>

Alternatives

  • Create a new IntlListFormatter instance instead of reusing and reconstructing the same object.
  • Never call __construct() manually after the object has already been created with new.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Invalid argument supplied for foreach()

Description

foreach() works on arrays or objects. For the array, all the elements of the array are read; for the objects, it is either the public properties, read like an array, or the Iterator interface, which uses specific methods.

Then, any other type is forbidden to be used with foreach(). This means all scalars elements, including string, integer and null.

Example

<?php

foreach(1234 as $b) {
	echo $b;
}

?>

Alternatives

  • Check that the source of the foreach can be used with is_iterable().

In more recent PHP versions, this error message is now :ref:foreach()-argument-must-be-of-type-array|object.

Invalid characters passed for attempted conversion, these have been ignored

Description

This error is emitted when a character outside the range of validity is used.

In the example above, the octdec() function converts a string from octal to decimal. Octals are written with figures from 0 to 8. In this case, 9 is excluded.

The same error is emitted with the other maths bases : for example, using ‘a’ in a decimal, or ‘X’ in a hexadecimal, etc.

Example

<?php

// 9 is not an octal and can't be converted
$decimal = octdec(342391);

// same as above, but the 9 is hidden with the octal notation (starts with 0)
$decimal = octdec(01234567);

?>

Alternatives

  • Check that the characters are in the correct range before attempting the conversion.

Invalid indentation - tabs and spaces cannot be mixed

Description

Since PHP 7.3, HEREDOCS and NOWDOCS syntax allows the text to be indented by the same amount than the closing tag (here X). The indentation must be built with only spaces or only tabulations, and cannot be a mix of both.

Example

<?php

$x = <<<X
       classic text
	 X // one tabulation + one space

?>

Alternatives

  • Make the indentation spaces only.
  • Make the indentation tabulations only.

Invalid numeric literal

Description

This error reports an invalid number, hardcoded in the source code.

Numbers are written with digits, without delimiters such as simple or double quotes. Then, they are converted in PHP’s internal representation of a number, and this is where error may arise.

In particular, integers have an upper and lower limit, PHP_INT_MAX and PHP_INT_MIN. Although, in that case, they are turned into a float, with loss of precision but no warning.

Then, PHP supports binary, octal and hexadecimal format. In the case above, the o signals an octal number, written with digits from 0 to 7. 8 is not allowed, and is not parsed by PHP.

This is also the case for illegal characters in binary (anything other than 1 and 0), or hexadecimal (anything other than digits, and letters from a and f).

An old convention was to consider octal any number that starts with a leading 0.

Example

<?php 

echo 0o78;

echo 078;

?>

Alternatives

  • Fix the number and use valid digits.
  • Drop the initial 0 to make the number decimal, not octal.
  • Add quotes to make this number a string, not a parsed number.

Invalid UTF-8 codepoint escape

Description

PHP supports unicode as escape sequence. They are used in double-quoted strings, and use the \u{73} format. The digits must represent a valid unicode codepoint: here, 73 represents the ASCII letter s.

When the prefix \u{ is detected, PHP tries to understand the next characters as an integer. When this is not the case, it fails the codepoint detection and stops.

In particular, it is not possible to use the _ number separator in these sequences.

Example

<?php

    $a = "\u{fgh}";

    echo \u{1F4_18};

?>

Alternatives

  • Check the values inside the curly braces: chances are it needs to be replaced with smaller values.
  • If there is no intent to use unicode codepoint, add \ to make PHP handle it as a literal value.

Invalid UTF-8 codepoint escape: Codepoint too large

Description

PHP supports unicode as escape sequence. They are used in double-quoted strings, and use the \u{73} format. The digits must represent a valid unicode codepoint: here, 73 represents the ASCII letter s.

When a valid escape sequence is detected, PHP use the integer between the curly braces. Unicode comprises 1,114,112 code points in the range 0 to 10FFFF. Beyond that value, codepoint are undefined, and do not represent anything anymore.

Example

<?php
  $a = "\u{ffffff}";
?>

Alternatives

  • Check the values inside the curly braces: chances are it needs to be replaced with smaller values.

Io\Poll\Handle cannot be implemented by user classes

Description

PHP 8.6 introduces a native Polling API (Io\Poll) for waiting on readiness of multiple I/O resources at once, backed by epoll or kqueue at the system level. Io\Poll\Handle is the marker interface that identifies a resource as pollable; it declares no methods of its own.

Every concrete handle type must register a low-level php_poll_handle_ops operations table that tells the polling backend how to obtain the underlying file descriptor and check the handle’s validity. Userland classes have no way to provide that table, so implementing Io\Poll\Handle directly from PHP code is rejected with a fatal error at class-declaration time, rather than producing a handle that would silently fail to work with the poller.

Example

<?php

class MyHandle implements Io\Poll\Handle {
}

?>

Literal Examples

  • Io\Poll\Handle cannot be implemented by user classes

Alternatives

  • Use one of the internal classes that already implement Io\Poll\Handle (such as a stream or socket resource wrapper), instead of implementing the interface yourself.
  • Wrap or compose an existing pollable resource rather than trying to make an arbitrary object pollable.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

‘%s’ is an invalid class name

Description

This error is emitted when a fully qualified name is used as a type (property, constant, parameter, returntype), and that cannot be a valid name. For example, this applies to \self, \static, \parent. Other keywords, such as true, null get a different error message.

Note also that all keywords are not covered with this error message, and some have slipped through the checks: for example, \interface, \class, \enum, \resource… are all valid code. In fact, PHP won’t create objects of such types, so this makes such type unusable.

Example

<?php

class X {
	function foo(\self $s) {}
}

?>

Literal Examples

  • ‘\self’ is an invalid class name
  • ‘\parent’ is an invalid class name
  • ‘\static’ is an invalid class name

Alternatives

  • Do not use PHP keywords as fully qualified name with a type.

is an invalid offset

Description

The requested value could not be found in the underlying array.

Indeed, the SplDoublyLinkedList has only 3 elements, none with the 4 index.

The problem also arise when using add method, with an index that is negative, or beyond the current last element of the list.

Traditional PHP array do not report this error: they return null, with the Undefined array key warning.

Example

<?php

$a = new SplDoublyLinkedList();
$array = [1,2,3];

foreach($array as $k => $v){
    $a->add($k,$v);
    
    // error when writing on an index out of bound
    // the first $k + 1 is beyond the count of the list (0), and fails.
    $a->add($k + 1,$v);
}

// error when accessing an index out of bound
print $a[4];

?>

Literal Examples

  • SplDoublyLinkedList::add(): Argument #1 ($index) is out of range

Alternatives

  • Check that the index in positive, and below the current number of elements in the list.

is an unsupported rounding mode

Description

This error is generated when a rounding error is used with bcround() or the BCMath\Number::round() method is used.

Example


Alternatives

  • Check documentation for the valid rounding enumerations.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

is not a valid codepoint

Description

Some functions uses integers to represents UTF-8 characters, on top of their string representation. When an integer is provided, it has to represent an actual character, in the UTF-8 range.

In particular, the character cannot be negative, or bigger than 55296.

Example

<?php

mb_substitute_character(-10);

?>

Alternatives

  • Check for the integer value before using it: it must be between 0 and 55296.
  • Use a string representation, with an escape sequence.

Iterator %s returned an invalid value (must return a string, a stream, or an SplFileInfo object)

Description

Phar::buildFromIterator() (and PharData::buildFromIterator()) adds one archive entry per value produced by the given iterator. Each value it receives must be either a string (the content of the file), a stream resource, or an SplFileInfo object (or subclass, such as SplFileObject) pointing at the file to add; the corresponding key is used as the entry’s path inside the archive.

If the iterator yields anything else, such as an integer, an array, or a plain object that is not an SplFileInfo, PHP cannot turn it into archive content and throws this UnexpectedValueException, naming the iterator’s class.

Example

<?php

class MyIterator implements Iterator {
    private array $items = ['a.txt', 42, 'b.txt'];
    private int $pos = 0;

    public function current(): mixed { return $this->items[$this->pos]; }
    public function key(): mixed { return $this->pos; }
    public function next(): void { $this->pos++; }
    public function rewind(): void { $this->pos = 0; }
    public function valid(): bool { return isset($this->items[$this->pos]); }
}

$phar = new PharData('/tmp/archive.tar');
$phar->buildFromIterator(new MyIterator());

?>

Literal Examples

  • Iterator MyIterator returned an invalid value (must return a string, a stream, or an SplFileInfo object)

Alternatives

  • Make sure every value the iterator yields is a string, a stream resource, or an SplFileInfo (e.g. SplFileObject) instance.
  • Use RecursiveDirectoryIterator or a similar built-in filesystem iterator, which naturally yields SplFileInfo objects.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Iterator does not support rewinding

Description

Iterators are executed one way, and cannot be rewind: once they have reached the end of their list of value, they stay there. Some Iterator subclasses are able to rewind at the beginning of the list, though.

Example

<?php

$XML = <<< XML
<root>
  <item>1</item>
  <item>2</item>
  <item>3</item>
</root>
XML;

$dom = new DomDocument();
$dom->loadXml($XML);
$items = $dom->getElementsByTagName('item');

echo 'Count: '.count($items).PHP_EOL;
echo 'Count: '.iterator_count($items->getIterator()).PHP_EOL;
$it = new IteratorIterator($items);
echo 'Count: '.iterator_count($it).PHP_EOL;
echo 'Count: '.iterator_count($it).PHP_EOL;

?>

Alternatives

  • Create a second iterator, based on the first one, and run the second operation with it.
  • Replace the usage of the Iterator by a subclass, that accepts rewind, such as ArrayIterator.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled.

Description

The root cause is that PHP’s JIT has a fundamental incompatibility with extensions that override the engine’s core execution handler zend_execute_ex().

When such an extension is loaded, PHP proactively disables JIT and shows that warning.

This issue goes far beyond just debuggers and coverage tools. Any extension that instruments code, like profilers, APMs, and security modules, can trigger it.

  • Debuggers & Code Coverage: xdebug, pcov, xhprof, pinba, suhosin
  • Performance & APM Tools: blackfire, newrelic, tideways_xhprof, ddtrace, solarwinds
  • Security Modules: bt_security_notice, bt_safe, imunify360
  • Async & Server Frameworks swoole
  • PHP Internals & Testing (Zend DTrace, uopz (User Operations for Zend), Zend Observer API (older implementations))
  • Other APM & Instrumentation: skywalking

Note: the list above is not exhaustive.

Example


Alternatives

  • Manage Development vs Production: for extensions that are meant for development, like xdebug and pcov, the simplest solution is to only load them in your development environment, such as by using different php.ini files.
  • Check for Alternative APIs or Versions: the newer Zend Observer API is the most JIT-friendly method for instrumenting code. Modern versions of tools like newrelic may support JIT by using this API, so always consult an extension’s latest documentation.
  • Consult Vendor Docs: many vendors provide specific JIT guidance. For instance, specific settings can be used to allow JIT to work with imunify360.
  • Disable JIT by setting opcache.jit=disable in the php.ini or via -d directive.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

jump into a finally block is disallowed

Description

It is not possible to make a goto, when the label is in a finally block. It is OK to do the goto call when both goto and label are in the finally block, though.

Example

<?php

goto theLabel;

try {}
catch (Exception) {}
finally {
	theLabel: 
		$a++;
}

?>

Alternatives

  • Replace the goto call with something else.
  • Move the goto in the finally block.
  • Move the label out of the finally block.

jump out of a finally block is disallowed

Description

It is not possible to make a goto, when the label is in a finally block. It is OK to do the goto call when both goto and label are in the finally block, though.

Example

<?php


try {}
catch (Exception) {}
finally {
	goto theLabel;
}

	theLabel: 
		$a++;

?>

Alternatives

  • Replace the goto call with something else.
  • Move the goto after the finally block.
  • Move the label in the finally block.

Key element cannot be a reference

Description

In a foreach() loop, the value may be a reference, when it needs to be updated. The key, on the other hand, cannot be changed, and hence, cannot have a reference.

Example

<?php

foreach($array as &$key => $value) {}

?>

Alternatives

  • Remove the reference from the key.
  • Use array_flip() to make the keys the values, and update them, then use the same function again.

Keys must be of type int|string during array unpacking

Description

Argument unpacking is the transformation of an array into a list of arguments. With arrays, the keys can only be integers or strings: they will be used for positional and named arguments, respectively.

Argument unpacking also applies to iterator and generator. In that case, it is possible to have keys that are not of type integer or string: they might be of any type. Yet, the unpacking of arguments needs these types to understand what kind of arguments is involved.

Any other type is forbidden : null, boolean, float (even without decimal part), and objects with __toString() magic methods. There is not type juggling applied, with or without strict_types directive.

Example

<?php
function foo(...$args) {
    var_dump($args);
}
function gen() {
    yield 1.23 => 123;
    yield '2.34' => 234;
}

try {
    print_r([...gen()]);
} catch (Error $ex) {
    echo 'Exception: ' . $ex->getMessage() . PHP_EOL;
}

?>

Alternatives

  • Ensure the iterator yields only integer or string types.
  • Ensure the generator yields only integer or string types.

Label ‘%s’ already defined

Description

A goto label has been defined twice or more. This is not allowed, as the goto call won’t be able to decide which label to reach.

Note that a single unused label is allowed, and is considered dead code.

Multiple identical labels are possible, in different method contexts.

Example

<?php

function foo() {
	C:
	C:
	
	// valid code, though dead and unused
	D: 
}

function bar() {
	// valid code, though dead and unused
	D: 
}

?>

Literal Examples

  • Label ‘C’ already defined

Alternatives

  • Remove duplicate label.
  • Rename duplicate label.
  • Move the duplicate label to a distinct method.

Looking up the DSN from a URI is deprecated due to possible security concerns with DSNs coming from remote URIs

Description

PDO supports a uri: DSN prefix: instead of passing the real DSN, an application could pass uri: followed by a URI, and PDO would fetch the actual DSN string from the resource that URI points to. The URI could name a local file, but could also be a remote URL fetched through a stream wrapper.

Fetching connection credentials from an arbitrary, potentially remote, URI on every connection is risky: with drivers such as SQLite it could be abused to read arbitrary files on the server, and remote URIs add an unpredictable performance cost and an extra trust boundary. This lookup mechanism is therefore deprecated.

Example

<?php

$pdo = new PDO('uri:file:///etc/myapp/dsn.txt');

?>

Alternatives

  • Read the DSN from the file yourself in userland code (for example with file_get_contents() against a local, trusted path) and pass the resulting string directly to the PDO constructor.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Making a constructor a Generator is deprecated

Description

Using yield anywhere in the body of __construct() turns it into a Generator function. Because a Generator’s body only starts running once it is iterated (and nothing iterates a constructor), the code inside such a constructor never runs when the object is created with new: initialization is silently skipped.

Since this pattern is virtually always a mistake, PHP 8.6 deprecates making a constructor a Generator.

Example

<?php

class X {
    public function __construct() {
        yield 1;
    }
}

new X;

?>

Literal Examples

  • Making a constructor a Generator is deprecated

Alternatives

  • Move the code that uses yield into a separate, regular method, and call it (or return its Generator) explicitly instead of relying on __construct().
  • If the constructor only needs to assign properties, replace yield with plain assignments.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See constructorAsGenerator

Making a destructor a Generator is deprecated

Description

Using yield anywhere in the body of __destruct() turns it into a Generator function. A Generator only starts executing once something iterates it, but nothing iterates the return value of a destructor: PHP just calls it during garbage collection and discards the result. As a consequence, the body of such a destructor never actually runs, silently skipping any cleanup code it contains.

Since this pattern is virtually always a mistake, PHP 8.6 deprecates making a destructor a Generator.

Example

<?php

class X {
    public function __destruct() {
        yield 1;
    }
}

$x = new X;
unset($x);

?>

Literal Examples

  • Making a destructor a Generator is deprecated

Alternatives

  • Move the code that uses yield into a separate, regular method that __destruct() calls directly.
  • If the destructor only needs to release resources, replace yield with plain statements.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See destructorAsGenerator

Match expressions may only contain one default arm

Description

match() expression may have one default entry, but no more than that. It is the same than for switch().

Example

<?php

$a = match($b) {
	default => 1;
	default => 2;
}

?>

Alternatives

  • Remove one of the default arm.
  • Remove all the default arms.

Maximum depth of %d exceeded. The depth limit can be changed using the max_depth unserialize() option

Description

PHP 7.4 introduced an option with the unserialize() function. It is called max_depth and it limits the number of nesting levels that unserialize allows, when producing the PHP structures. This saves memory and processing power.

Example

<?php

// 4 levels of nesting
$a = [[[[]]]];

$string = serialize($a);

print_r(unserialize($string, ['max_depth' => 2]));

?>

Literal Examples

  • Maximum depth of 2 exceeded. The depth limit can be changed using the max_depth unserialize() option

Alternatives

  • Remove the option from the call to unserialize().
  • Check the string and count the level of nesting, before calling unserialize().

Maximum execution time of %d second%s exceeded

Description

This error indicates that the application has been running for longer than an acceptable amount of time: by default, 30 seconds.

To avoid working indefinitely on a task, PHP cancels its execution.

It is common to set this duration to low levels, so as to keep execution time short. In a production environement, any such error should be investigated, and refactored.

Example

<?php

// an infinite loop that will break beyond max execution time, eventually
for(;;) {}

?>

Literal Examples

  • Maximum execution time of 30 seconds exceeded

Alternatives

  • Write faster PHP code.
  • Write lighter PHP code.
  • Update the configuration directive max_execution_time for the whole application.
  • Update the configuration directive max_execution_time for a part of the application.

Method %pS::%pS() does not exist

Description

The ReflectionMethod constructor requires the name of a method that actually exists on the given class (or object). When no such method is declared, either directly on the class or via one of its parents, traits or interfaces, the Reflection API cannot build the requested introspection object and throws a ReflectionException instead.

Example

<?php

class X {}

$reflection = new ReflectionMethod('X', 'doesNotExist');

?>

Literal Examples

  • Method X::doesNotExist() does not exist

Alternatives

  • Check the method name for typos, including its case.
  • Use method_exists() or ReflectionClass::hasMethod() to check the method is available before reflecting on it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Method %s::%s() cannot be static

Description

Some PHP special methods cannot be static. This is the case of all the PHP magic methods, such as the constructor __construct, the destructor __destruct, and all the others: __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize(), __unserialize(), __toString(), __invoke(), __set_state(), __clone() and __debugInfo().

Example

<?php

class X {
	static function __construct() {}
}

?>

Literal Examples

  • Method x::__construct() cannot be static

Alternatives

  • Make a static method that can call the method that would be static. Be aware, this will require the building of an object, as a static method does not set $this.

Method %s::%s() cannot declare a return type

Description

There can be no return type for certain methods, such as the constructor and the desctructor.

The constructor is called while creating a new instance of an object, but it doesn’t return the object itself.This is the case even if $this is available in the method.

The destructor is called while destroying an instance, and shall not return anything.

Theses methods must remain without a return type: not void, not mixed, not never, or anthing else.

Example

<?php

class X {
	function __construct() : int {	}
	function __destruct() : string {	}
}

?>

Literal Examples

  • Method X::__construct() cannot declare a return type
  • Method X::__destruct() cannot declare a return type

Alternatives

  • Remove the return type of the method.

Method %s::%s() must be static

Description

The magic methods __set_state and __callStatic must be static. These are the only magic methods that must be static.

Example

<?php

class X {
    function __set_state($state) {}
}
?>

Alternatives

  • Add static to the method signature, and remove all $this in its body.
  • Remove the methods.

Method %s::%s() must take exactly 1 argument

Description

This error reports that a method requires one and only one argument. It applies to methods such as __set_state() and __get.

It may be surprising that it is a compile time error. Actually, the faulty method is a magic method, so PHP already knows what signature is expected for that method.

Example

<?php

class X {
    function __set_state() {}
}

?>

Literal Examples

  • Method X::__set_state() must take exactly 1 argument

Alternatives

  • Use one argument for this method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Method %s::%s() must take exactly 2 arguments

Description

This error reports that a method requires two and only two arguments. It applies to methods such as __set().

It may be surprising that it is a compile time error. Actually, the faulty method is a magic method, so PHP already knows what signature is expected for that method.

Example

<?php

class X {
    function __set() {}
}

?>

Literal Examples

  • Method X::__set() must take exactly 2 arguments

Alternatives

  • Use one argument for this method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Method %s::%s cannot be #[\NoDiscard] error_type

Description

The #[\NoDiscard] attribute marks a function, method or closure so that the engine emits a warning whenever a caller ignores its return value. A number of magic methods – __clone, __set, __unset, __wakeup and __unserialize – are expected to always behave as if declared : void: PHP calls them purely for their side effect and never looks at, or exposes, any value they might return. Marking one of them #[\NoDiscard] is therefore meaningless, and PHP rejects it at compile time.

This is the same wording as the message used for __construct and __destruct (see method-%s::%s-cannot-be-#[–nodiscard]), but produced by a different internal check: those two magic methods are not even allowed to declare a return type at all, whereas the methods covered here are simply always treated as implicitly void. The trailing ‘error_type’ in this file’s identifier is an artifact of how this catalog extracts messages from the PHP source; it is not part of the text PHP actually displays.

Example

<?php

class X {
    #[\NoDiscard]
    public function __clone() {}
}

$x = new X();
clone $x;

?>

Literal Examples

  • Method X::__clone cannot be #[\NoDiscard]
  • Method X::__set cannot be #[\NoDiscard]
  • Method X::__unset cannot be #[\NoDiscard]
  • Method X::__wakeup cannot be #[\NoDiscard]
  • Method X::__unserialize cannot be #[\NoDiscard]

Alternatives

  • Remove the #[\NoDiscard] attribute from the magic method.
  • If a discardable-value warning is needed, move the logic to a regular, non-magic method and mark that one instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Method %s::%s cannot be #[\NoDiscard]

Description

The #[\NoDiscard] attribute marks a function, method or closure so that the engine emits a warning whenever a caller ignores its return value. Certain magic methods, such as __construct, __destruct, __clone and __wakeup, are always invoked for their side effect and never return a usable value to the caller (new returns the object itself, not the constructor’s return value), so attaching #[\NoDiscard] to them is meaningless and rejected at compile time.

Example

<?php

class X {
    #[\NoDiscard]
    public function __construct() {}
}

new X();

?>

Literal Examples

  • Method X::__construct cannot be #[\NoDiscard]

Alternatives

  • Remove the #[\NoDiscard] attribute from the magic method.
  • If a discardable-value warning is needed, move the logic to a regular, non-magic method and mark that one instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Method %s::__construct() cannot declare a return type

Description

There can be no return type for a constructor method. It is called while creating a new instance of an object, but it doesn’t return the object itself. This is the case even if $this is available in the method.

Example

<?php

class X {
	function __construct() : int {
	
	}
}

?>

Literal Examples

  • Method X::__construct() cannot declare a return type

Alternatives

  • Remove the return type of the method.

In previous PHP versions, this error message used to be :ref:constructor-%s::%s()-cannot-declare-a-return-type.

Method %s::__toString() must not throw an exception, caught %s: %s

Description

Until PHP 8.0, __toString could not throw exception, and would end up with this error. In PHP 8.0, it is now possible.

Example

<?php

class X {
    function __toString() {
        throw new \Exception('error');
    }
    
    function foo() {
        throw new \Exception('error');
    }
    
}

?>

Literal Examples

  • Method X::__toString() must not throw an exception, caught Exception: error

Alternatives

  • Upgrade to PHP 8.0.
  • Store the error in another property, and check the property in another method, after the call to __toString.

Method name must be a string

Description

When using a dynamic syntax to call a method, the name of the method must be a string. It cannot be any other type, as no type juggling will take place. In particular, objects with toString are not converted to their string value.

Although method names have a specific format, this is not checked here, and the string is used raw.

Note that there is not equivalent for dynamic property names: they are cast to string as needed.

Example

<?php

class X {
    static function foo() {}
}

$b = 1;
X::$b();

?>

Alternatives

  • Cast the variable to string first, with (string).
  • Check if the variable is a string before using it.
  • Use a switch to hardcode the method name.

Methods with the same name as their class will not be constructors in a future version of PHP; %s has a deprecated constructor

Description

In PHP 4, the constructor of a class was the method with the same name as the class. In the example, the X::X method is the constructor. This was deprecated in PHP 7.0, in favor of using the __construct method.

During the deprecation phase, the eponymous method was still used as the constructor, if the __construct method was not available.

Example

<?php

class X {
    function X() {}
}

?>

Alternatives

  • Rename the eponymous method to __construct.
  • Crete the __construct method, and make it call the eponymous method.

Missing format specifier at end of string

Description

This error is related to the parsing of the format string. In the first example, PHP finds two % characters, and expect each time to be followed by a format character. When the % is at the end of the string, there is no more character to parse, hence the error message.

Also, note the second illustration, which uses a dot . after the %. This is a padding character, so the parser set it aside, and then, look for the format character itself, while reaching the end of the line.

This error applies to printf(), sprintf(), vprintf(), vsprintf().

Example

<?php

    printf('%s %', 'a', 'b');
    printf('%s %.', 'a', 'b');

?>

Alternatives

  • Add the missing format character at the end of the line.
  • Remove the final % char in the format line.
  • Add another % at the end of the line, to make it a literal % char in the format.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Modification of SplObjectStorage during getHash() is prohibited

Description

SplObjectStorage internals are not reentrant during hashing.

Example

<?php

class WatchfulStorage extends SplObjectStorage {
    public SplObjectStorage $sideStorage;
    public function getHash(object $object): string {
        $this->sideStorage->offsetSet(new stdClass());
        return spl_object_hash($object);
    }
}

$watch = new WatchfulStorage();
$watch->sideStorage = new SplObjectStorage();

try {
    $watch->offsetSet(new stdClass());
    echo "offsetSet succeeded, sideStorage count=".count($watch->sideStorage)."\n";
} catch (\Error $e) {
    echo "Error: ".$e->getMessage()."\n";
}

?>

Alternatives

  • Do not change the object during hashing. Change it with another method call.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See splObjectStorageGetHashMutation86

Module “%s” is already loaded

Description

The current configuration of the PHP engine include twice the same extension. The first extension is loaded and the last extension is omitted. The features are available, and the log will be filled with the warning.

PHP uses several distinct files to list the extensions to load, such as php.ini, cond.d/*.ini, and the SAPI configuration files, including the web server, CLI’s php.ini, etc.

Example


Literal Examples

  • Module “imagick” is already loaded

Alternatives

  • Find the duplicate extension configuration and remove all of the, but one.

Multiple %s modifiers are not allowed

Description

A single modifier keyword (final, static, readonly, or a visibility keyword such as public, protected, private) is enough to apply that property to a class member. Repeating the same kind of modifier twice in a declaration is redundant and rejected by the parser.

This is a generic, templated message: the concrete modifier name takes the place of %s. There are dedicated, more specific messages for each modifier family: final, static, readonly, and the access-type (visibility) modifiers.

Example

<?php

class X {
    final final function foo() {}
}

?>

Literal Examples

  • Multiple final modifiers are not allowed
  • Multiple static modifiers are not allowed
  • Multiple readonly modifiers are not allowed
  • Multiple access type modifiers are not allowed

Alternatives

  • Remove the duplicate modifier, keeping only one occurrence.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Multiple access type modifiers are not allowed

Description

Only one visibility option is necessary to set the visibility of a property. Two is overkill or could be impossible, so PHP reports it.

This message applies to private, protected and public options.

This message appears when compiling PHP 8.4+ code, with asymmetric visibility, against PHP 8.3 or older. In that case, protected(set) is not recognized as a token, and only the protected part is used, leading to the error.

There are similar messages for multiple readonly, or multiple static.

Example

<?php

class X {
	private private static A $b;
}

class Y
{
    public protected(set) string $name;
}

?>

Alternatives

  • Drop the extra visibility, and keep only one.
  • Compile with PHP 8.4 and more recent.
  • Remove asymmetric visibility.

Multiple final modifiers are not allowed

Description

One mention of the final option is sufficient to make a method so.

Example

<?php

class X {
    final final function foo() {}
}

?>

Alternatives

  • Keep only one mention of final.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Multiple readonly modifiers are not allowed

Description

Only one readonly option is necessary to make a property read-only. Two is overkill, and not needed, so PHP reports it.

There are similar messages for multiple visibility, or multiple static.

Example

<?php

class X {
	private readonly readonly A $b;
}

readonly readonly class Y {
}

?>

Alternatives

  • Drop the extra readonly, and keep only one.
  • Drop all the readonly options.

Multiple static modifiers are not allowed

Description

Only one static option is necessary to make a property static. Two is overkill, and not needed, so PHP reports it.

There are similar messages for multiple readonly, or multiple static.

Multiple static on a closure or arrow function leads to a parse error.

Example

<?php

class X {
	private static static A $b;

	private static static function a() {}
}

static static function () {}; 

?>

Alternatives

  • Drop the extra static, and keep only one.
  • Drop all the static options.

must be a bitmask of POSIX_F_OK, POSIX_R_OK, POSIX_W_OK, and POSIX_X_OK

Description

posix_access() checks whether the current process can access a file in a given way. Its $flags argument only accepts a bitmask built from POSIX_F_OK (existence), POSIX_R_OK (readable), POSIX_W_OK (writable), and POSIX_X_OK (executable).

As of PHP 8.6, passing a value with bits set outside of that set throws a ValueError, instead of forwarding an unvalidated flag value straight to the underlying access() system call.

Example

<?php

posix_access('/etc/passwd', 999);

?>

Literal Examples

  • posix_access(): Argument #2 ($flags) must be a bitmask of POSIX_F_OK, POSIX_R_OK, POSIX_W_OK, and POSIX_X_OK

Alternatives

  • Build $flags for posix_access() only out of POSIX_F_OK, POSIX_R_OK, POSIX_W_OK, and POSIX_X_OK, combined with | as needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, an out-of-range $flags value was passed through to the underlying access() call unchecked instead of being rejected.](Previously, an out-of-range $flags value was passed through to the underlying access() call unchecked instead of being rejected.)

must be a callable, null given

Description

The PDOStatement::fetchAll() accepts a 2nd argument as a callback. That method processes the returning rows before they are returned by the method itself. By default, the method returns arrays, and doesn’t need the callback. When the callback is provided, it must be a valid callback, and, as such, can’t be null.

This error is the same as Argument #%d ($name) must be of type %s, %s given, but is specific to the PDO extension, and the PDOStatement::fetchAll(). The original problem is also the same.

Example

<?php

// Connection to the database
$db = new Pdo();

// Dummy valid SQL query
$stmt = $db->query('SELECT * FROM table');

try {
    var_dump($stmt->fetchAll(PDO::FETCH_FUNC, NULL));
} catch (\Throwable $e) {
    echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}

?>

Alternatives

  • Remove the second $callback argument in the call to the PDOStatement::fetchAll() method.
  • Use a valid second $callback argument in the call to the PDOStatement::fetchAll() method.

must be a combination of MSG_OOB, MSG_PEEK, MSG_WAITALL, MSG_DONTWAIT, MSG_ERRQUEUE, and MSG_CMSG_CLOEXEC for AF_PACKET sockets

Description

PHP 8.6 adds raw AF_PACKET support to socket_recvfrom(). On a packet socket, only a finite subset of MSG_* flags is safe to use for receiving: MSG_OOB, MSG_PEEK, MSG_WAITALL, MSG_DONTWAIT, MSG_ERRQUEUE, and MSG_CMSG_CLOEXEC. Notably, MSG_TRUNC is excluded, since on a packet socket it makes recvfrom() report the untruncated frame length, which can exceed the supplied buffer.

Passing any flag outside this set on an AF_PACKET socket throws a ValueError, instead of risking a buffer-size mismatch.

Example

<?php

$socket = socket_create(AF_PACKET, SOCK_RAW, 0);

socket_recvfrom($socket, $data, 2048, MSG_TRUNC, $address, $port);

?>

Literal Examples

  • socket_recvfrom(): Argument #4 ($flags) must be a combination of MSG_OOB, MSG_PEEK, MSG_WAITALL, MSG_DONTWAIT, MSG_ERRQUEUE, and MSG_CMSG_CLOEXEC for AF_PACKET sockets

Alternatives

  • When calling socket_recvfrom() on an AF_PACKET socket, only combine flags from MSG_OOB, MSG_PEEK, MSG_WAITALL, MSG_DONTWAIT, MSG_ERRQUEUE, and MSG_CMSG_CLOEXEC.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be a concrete class

Description

stream_wrapper_register() and stream_filter_register() associate a class name with a protocol (or filter) name; the streams layer instantiates that class itself whenever the protocol is opened or the filter is applied. Passing an abstract class, or an interface, means there is nothing the streams layer could ever instantiate.

Previously, this only failed later, when PHP actually tried to open a stream using the unusable class. As of PHP 8.6, both functions check that the class is instantiable up front and throw immediately, instead of registering a class that is guaranteed to fail on first use.

Example

<?php

abstract class MyProtocol {}

stream_wrapper_register('myproto', MyProtocol::class);

?>

Literal Examples

  • stream_wrapper_register(): Argument #2 ($class) must be a concrete class

Alternatives

  • Register a concrete (non-abstract) class that implements the expected stream wrapper or filter interface.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be a finite value

Description

This error is raised when a parameter was provided with an infinite value.

Infinite values are generated by maths functions such as atan or log, and also with the INF and NAN constants. Infinite values are considered to be typed float.

For example, stream_socket_client() and stream_socket_accept() require a $timeout parameter, and it is tempting, but not valid, to provide INF.

Example

<?php

$fp = stream_socket_client(tcp://www.example.com:80, $errno, $errstr, INF);

?>

Alternatives

  • Use a very large, but finite float value, such as PHP_FLOAT_MAX, which will be valid until the end of the universe, even in nanoseconds.

must be a list array

Description

This error is reported when the provided list of parameters, in mysqli_stmt_execute() or mysqli::stmt_execute() is not a list: the index must start at 0, and be auto-generated.

Example

<?php

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect('localhost', 'my_user', 'my_password', 'world');

mysqli_query($link, 'CREATE TEMPORARY TABLE myCity LIKE City');

/* Prepare an insert statement */
$stmt = mysqli_prepare($link, 'INSERT INTO myCity (Name, CountryCode, District) VALUES (?,?,?)');

$val1 = 'Stuttgart';
$val2 = 'DEU';
$val3 = 'Baden-Wuerttemberg';

/* Execute the statement */
mysqli_stmt_execute($stmt, [$val1, $val2, 'val' => $val3]);

?>

Alternatives

  • Check that no index is explicitly named in the array of parameters.
  • Apply array_values() to make the array a list.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be a list of %s

Description

Uri\WhatWg\InvalidUrlException::__construct() accepts an $errors argument describing every WHATWG URL validation failure that occurred. That argument must be a list (contiguous, zero-based keys) whose every value is an instance of Uri\WhatWg\UrlValidationError. Any other array shape — associative keys, non-sequential indices, or elements that are not UrlValidationError objects — is rejected with this ValueError.

Example

<?php

new Uri\WhatWg\InvalidUrlException(
    'bad url',
    ['not a validation error object'],
);

?>

Literal Examples

  • Uri\WhatWg\InvalidUrlException::__construct(): Argument #2 ($errors) must be a list of Uri\WhatWg\UrlValidationError

Alternatives

  • Pass an array of Uri\WhatWg\UrlValidationError instances only, built with array_values() if it might have gaps or string keys.
  • Let the WHATWG URL parser construct and throw this exception itself, rather than constructing it manually.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be a multiple of argument #2 ($word_size)

Description

The second option of gmp_import() configures the number of bytes to take in the string to build the number. Each GMP digit will be read over $word_size characters. When the string has a length that is not a multiple of the size of each word, GMP will run short of a few bytes, and emits the error.

Example

<?php
gmp_import('aa', 3);
?>

Literal Examples

  • Argument #1 ($data) must be a multiple of argument #2 ($word_size)

Alternatives

  • Check that the string length is a multiple of the 2nd argument of gmp_import().
  • Use a word length that is a factor of the string length.
  • Use a word length of 1, which works all the time, yet may not yield the expected result.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be a user-defined class name, internal class name given

Description

class_alias() creates an alias for a class, an enumeration, an interface or a trait. Until PHP 8.3, it was only possible to create such aliases with custom structures, and it was not possible to do it with PHP native classes.

Example

<?php

class_alias(stdClass::class, MyClass::Class);

?>

Alternatives

  • Upgrade to PHP 8.3 or more recent.
  • Create a class that extends the PHP native class, and create an alias on this custom class.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See classAliasWithInternalClass

must be a valid charset

Description

This is a Windows only error. It is related to converting a string to another encoding, and failing. No information is available about it.

Example


Alternatives

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be a valid class name, %s given

Description

get_parent_class() expects an argument, which must be either an object, or a valid class name. The object’s class name will be used; for the valid class name, it is recommended to use the ::class operator on the class name, and also, to check if the class exists first.

Example

<?php

$a = 1;
get_parent_class($a);

?>

Literal Examples

  • must be a valid class name, null given
  • must be a valid class name, integer given

Alternatives

  • Check that the parameter is an object.
  • Make the string a valid class name, with the ::class operator.
  • Check if the string is an existing class, with a call to class_exists().

must be a valid comparison operator

Description

version_compare() compares version strings, using an operator, passed as third parameter. Until PHP 8.1, unknown operators are ignored, and use the default value.

Nowadays, it is generating a fatal error.

Valid operators are : <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne

Note that the 3rd parameter is case sensitive, so NE also yields the error.

Example

<?php

version_compare('1.2.4', '1.2.3', '?');

?>

Alternatives

  • Use a valid operator.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See version_compare

must be a valid context engine ID

Description

SNMP::setSecurity()’s $contextEngineId argument is expected to be a hex-encoded SNMPv3 context engine ID, which the extension decodes back to raw bytes before handing it to the underlying Net-SNMP session.

As of PHP 8.6, a value that cannot be decoded as hex throws a ValueError, instead of silently leaving the context engine ID unset on the session.

Example

<?php

$snmp = new SNMP(SNMP::VERSION_3, 'localhost', 'user');

$snmp->setSecurity('authPriv', 'SHA', 'authpass', 'AES', 'privpass', '', 'not-hex');

?>

Literal Examples

  • SNMP::setSecurity(): Argument #7 ($contextEngineId) must be a valid context engine ID

Alternatives

  • Pass a valid hex-encoded string as the $contextEngineId argument to SNMP::setSecurity(), or omit it to leave the context engine ID unset.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, this emitted an E_WARNING (“Bad engine ID value ‘%s’”) and left the context engine ID unset, instead of throwing.](Previously, this emitted an E_WARNING (“Bad engine ID value ‘%s’”) and left the context engine ID unset, instead of throwing.)

must be a valid encoding, “%s” given

Description

The encoding arguments, in any mb_ function, must be a supported encoding. Otherwise, the mbstring extension doesn’t know how to handle it.

The current list of encodings is available with the function mb_list_encodings(). Encoding names are case insensitive.

The list of supported encoding depends on the PHP version. Some are added or removed, depending on the version.

Example

<?php

	print mb_chr(128024, 'UTF-8')); // emoji of an elephant

	//Argument #2 ($encoding) must be a valid encoding, "elephpant" given 
	print mb_chr($value, 'elephpant'));
?>

Literal Examples

  • must be a valid encoding, “qprint” given
  • must be a valid encoding, “uuencode” given

Alternatives

  • Check the encoding with mb_list_encodings() before using one.

must be a valid method name

Description

The ReflectionMethod requires a method name to be instantiated. It is recommended to specify it with 2 arguments, the first being the class, or one of its objects, and the second being the method name.

When only one argument is provided, the string must have the class::method format.

Example

<?php

$method = new ReflectionMethod('c');

?>

Alternatives

  • Use two arguments to call this method.
  • Use the correct format to reprsent a method in a string.

must be a valid normalization form

Description

Normalizer::normalize() and Normalizer::isNormalized() accept a $form argument built from ICU’s Unicode normalization forms: Normalizer::FORM_D, ::FORM_KD, ::FORM_C (the default), ::FORM_KC, or ::FORM_KC_CF. Any other integer does not correspond to a form ICU knows how to normalize to.

This has thrown a ValueError since PHP 8.0; PHP 8.6 only corrected a typo in the message text itself, which previously doubled the word “a”.

Example

<?php

Normalizer::normalize('café', 999);

?>

Literal Examples

  • Normalizer::normalize(): Argument #2 ($form) must be a valid normalization form
  • Normalizer::isNormalized(): Argument #2 ($form) must be a valid normalization form

Alternatives

  • Pass one of Normalizer::FORM_D, ::FORM_KD, ::FORM_C, ::FORM_KC, or ::FORM_KC_CF as the $form argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [PHP 8.0 through 8.5 threw the same ValueError but with a typo in the message: “must be a a valid normalization form” (doubled “a”).](PHP 8.0 through 8.5 threw the same ValueError but with a typo in the message: “must be a a valid normalization form” (doubled “a”).)

must be a valid rounding mode (RoundingMode::*)

Description

PHP has 4 rounding modes, to be used with the round() native function. They are PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN, PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD; there is also RoundingMode and its cases : RoundingMode::HalfAwayFromZero, RoundingMode::HalfTowardsZero, RoundingMode::HalfEven, RoundingMode::HalfOdd, RoundingMode::TowardsZero, RoundingMode::AwayFromZero, RoundingMode::NegativeInfinity, RoundingMode::PositiveInfinity.

Any value that is not typed RoundingMode or is typed int but outside the 4 supported values and the default behavior of 0, produces this error message. In particular, false and null are not

Although the error message recommends using RoundingMode, the historical PHP_ROUND_* are still valid. It might be wise to start migrating to the new enumeration.

The GMP rounding function (via gmp_div_q()) works as previously. BCmath has no rounding function.

Example

<?php

// Generates the error
print $a = round(1.2, 2, 333);

// Generates the error
print $a = round(1.2, 2, 0);

// Generates the error
print $a = round(1.2, 2, false);

?>

Alternatives

  • Use a valid enum case to configure the round() function.
  • Use a valid PHP_ROUND_* constant to configure the round() function.
  • Remove the 3rd parameter altogether: this means using PHP_ROUND_HALF_UP.

must be between 1 and %lu

Description

gmp_root() and gmp_rootrem() compute the integer part of the $nth root of $num. Internally, $nth is passed to GMP as an unsigned long, so it must be at least 1 and cannot exceed the platform’s ULONG_MAX.

As of PHP 8.6, an $nth outside this range throws a ValueError naming the exact upper bound, instead of only rejecting non-positive values and letting an oversized $nth overflow when narrowed to an unsigned long.

Example

<?php

gmp_root('27', PHP_INT_MAX);

?>

Literal Examples

  • gmp_root(): Argument #2 ($nth) must be between 1 and 18446744073709551615
  • gmp_rootrem(): Argument #2 ($nth) must be between 1 and 18446744073709551615

Alternatives

  • Pass an $nth argument to gmp_root()/gmp_rootrem() between 1 and PHP_INT_MAX (or the platform’s ULONG_MAX, whichever is smaller).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, gmp_root() rejected only $nth <= 0 (“must be greater than 0”) and gmp_rootrem() rejected only $nth < 1 (“must be greater than or equal to 1”), without an upper bound.](Previously, gmp_root() rejected only $nth <= 0 (“must be greater than 0”) and gmp_rootrem() rejected only $nth < 1 (“must be greater than or equal to 1”), without an upper bound.)

must be between 1 and 7

Description

When processing days of the week as an integers, the days are represented by the integers from 1 (Monday) to 7 (Sunday). Other values are non used, and are reported as faulty.

Example

<?php

$c = new IntlGregorianCalendar(NULL, 'pt_PT');

try {
    var_dump($c->setMinimalDaysInFirstWeek(0));
} catch (\ValueError $e) {
    echo $e->getMessage() . \PHP_EOL;
}

?>

Alternatives

  • Use an integer with a value between 1 and 7.

%s(): Argument #%d ($%s) must be contained in argument #%d ($%s)

Description

strpos() searches for a string called $needle in another string called $haystack, starting at the offset passed as third argument, and called $offset.

The offset must be smaller than the full length of the $haystack: otherwise, PHP starts to search beyond the end of the data, and that will always fail.

This error message is shared by several PHP native and extension functions, namely mbstring and iconv: strpos(), strrpos(), stripos(), strripos(), mb_strpos(), mb_strrpos(), mb_stripos(), mb_strripos(), iconv_strpos and iconv_strrpos.

Before PHP 8.0, the failure was reported as a non-blocking warning. Since PHP 8.0, it is a fatal error.

Example

<?php

var_dump(strpos('abc', 'a', 4));

?>

Literal Examples

  • strpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)

Alternatives

  • Check that the offset is not beyond the length of the string.
  • Use a try catch around this methodcall.
  • Lengthen the source string.

In previous PHP versions, this error message used to be :ref:offset-not-contained-in-string..

must be either CASE_LOWER or CASE_UPPER

Description

array_change_key_case() converts every string key of an array to either all-lowercase or all-uppercase. Its second argument only accepts two values: CASE_LOWER (the default) or CASE_UPPER.

Previously, passing any other integer was silently treated as CASE_LOWER. As of PHP 8.6, the function validates the argument up front and throws a ValueError for anything else, instead of quietly falling back to the default.

Example

<?php

$array = ['FOO' => 1, 'BAR' => 2];

array_change_key_case($array, 2);

?>

Literal Examples

  • array_change_key_case(): Argument #2 ($case) must be either CASE_LOWER or CASE_UPPER

Alternatives

  • Pass either CASE_LOWER or CASE_UPPER as the second argument to array_change_key_case().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, any value other than CASE_UPPER was silently treated as CASE_LOWER.](Previously, any value other than CASE_UPPER was silently treated as CASE_LOWER.)

must be either Spoofchecker::LTR or Spoofchecker::RTL

Description

PHP 8.6 adds Spoofchecker::getBidiSkeleton() and Spoofchecker::areBidiConfusable(), which compute (or compare) the visual skeleton of a string for a given text direction, used to detect visually-confusable identifiers that mix left-to-right and right-to-left scripts. Both methods take a $direction argument that only accepts two values: Spoofchecker::LTR or Spoofchecker::RTL.

Passing any other integer raises a ValueError, since ICU’s bidi skeleton algorithm only knows how to reason about text in one of these two directions.

Example

<?php

$checker = new Spoofchecker();

$checker->getBidiSkeleton(99, 'paypal');

?>

Literal Examples

  • Spoofchecker::getBidiSkeleton(): Argument #1 ($direction) must be either Spoofchecker::LTR or Spoofchecker::RTL
  • Spoofchecker::areBidiConfusable(): Argument #1 ($direction) must be either Spoofchecker::LTR or Spoofchecker::RTL

Alternatives

  • Pass either Spoofchecker::LTR or Spoofchecker::RTL as the $direction argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be empty when class provided in argument #1 ($class) does not have a constructor

Description

The class referenced in the PDO::fetchObject method does not have a constructor. No argument will be handed to it, so there is no need to pass that argument.

Example

<?php

class X
{
    public $id;
    protected $val;
    private $val2;
}

$stmt->execute(); // STMT is a PDO statement
try {
    var_dump($stmt->fetchObject(X::class, [0]));
} catch (\Throwable $e) {
    echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}

?>

Alternatives

  • Omit the second argument.
  • Use an empty array for the second argument.
  • Use a null value for the second argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be empty when class provided in argument #2 ($class) does not have a constructor

Description

The class referenced in the PDO::fetchAll method does not have a constructor. No argument will be handed to it, so there is no need to pass that argument.

Example

<?php

class X
{
    public $id;
    protected $val;
    private $val2;
}

$stmt->execute(); // STMT is a PDO statement
try {
    var_dump($stmt->fetchAll(PDO::FETCH_CLASS, X::class, [0]));
} catch (\Throwable $e) {
    echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}

?>

Alternatives

  • Omit the third argument.
  • Use an empty array for the third argument.
  • Use a null value for the third argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be greater than 0

Description

This error is reported when a parameter is expected to be an integer, strictly positive. This is the case with the second argument of str_split().

Example

<?php
  str_split('abc', 0);
?>

Literal Examples

  • str_split(): Argument #2 ($length) must be greater than 0

Alternatives

  • Use a valid value for the parameter: a positive and non zero integer, for example 1, 2, 3…

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be greater than or equal to 1

Description

The second argument of gmp_import() is the number of characters to read in the original string, to build a GMP digit. This size must be 1 or larger, and the string’s length must be a multiple of that number.

Example

<?php
gmp_import('11', -2);
?>

Literal Examples

  • Argument #2 ($word_size) must be greater than or equal to 1

Alternatives

  • Use the default value of 1, by omitting it.
  • Use a postive number as second argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be less than 4294967295 bytes

Description

sodium_crypto_pwhash() and sodium_crypto_pwhash_str() derive a key, or a storable hash, from a password using the Argon2 algorithm. Internally, libsodium tracks the length of the password (and of the derived key or salt) in a 32-bit unsigned integer, so any input of 4294967295 bytes (2^32 - 1) or more cannot be represented and can never be processed.

As of PHP 8.6, these out-of-range length checks throw a ValueError naming the offending argument. Earlier versions threw a generic SodiumException instead for the same underlying condition.

Example

<?php

$hash = sodium_crypto_pwhash_str(str_repeat('a', 4294967295), SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE);

?>

Literal Examples

  • sodium_crypto_pwhash_str(): Argument #1 ($password) must be less than 4294967295 bytes

Alternatives

  • Do not pass passwords, salts or derived keys anywhere near 4 GB in size; hash a digest of the material instead if it is genuinely that large.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be less than argument #2 ($max)

Description

gmp_random_range() returns a random GMP number in the inclusive range [$min, $max]. That range only makes sense when $min is strictly less than $max.

This has thrown a ValueError for a non-positive range since PHP 8.0; PHP 8.6 only corrected the argument name referenced in the message, from the stub’s actual parameter name $max (it previously said $maximum, which never matched the real signature).

Example

<?php

gmp_random_range(10, 5);

?>

Literal Examples

  • gmp_random_range(): Argument #1 ($min) must be less than argument #2 ($max)

Alternatives

  • Make sure $min is strictly less than $max when calling gmp_random_range().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [PHP 8.0 through 8.5 threw the same ValueError but referenced the second argument as “$maximum”, which did not match the function’s actual $max parameter name.](PHP 8.0 through 8.5 threw the same ValueError but referenced the second argument as “$maximum”, which did not match the function’s actual $max parameter name.)

must be MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY, or one of the MYSQLI_OPT_* constants

Description

mysqli_options() (and mysqli::options()) only understand a fixed set of option constants: MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY, and the various MYSQLI_OPT_* constants. Each of these expects a specific value type (string, bool or int), which the function needs to know in order to validate and forward the value correctly.

Before PHP 8.6, passing an option value that mysqli_options() did not recognize was silently ignored: the call returned false without telling the caller why. As of PHP 8.6, an unrecognized option now throws a ValueError instead.

Example

<?php

$mysqli = mysqli_init();

mysqli_options($mysqli, 999999, true);

?>

Literal Examples

  • mysqli_options(): Argument #2 ($option) must be MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY, or one of the MYSQLI_OPT_* constants

Alternatives

  • Pass one of the documented MYSQLI_INIT_COMMAND, MYSQLI_SET_CHARSET_NAME, MYSQLI_SERVER_PUBLIC_KEY or MYSQLI_OPT_* constants as the option argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be no longer than %d characters

Description

IntlNumberRangeFormatter::createFromSkeleton()’s $locale argument is validated against ICU’s internal locale-name length limit before being parsed, the same limit enforced elsewhere across the intl extension.

Passing a $locale string longer than that limit throws a ValueError, instead of handing an oversized buffer to ICU’s locale parser.

Example

<?php

IntlNumberRangeFormatter::createFromSkeleton(
    '',
    str_repeat('a', 200),
    IntlNumberRangeFormatter::COLLAPSE_AUTO,
    IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE
);

?>

Literal Examples

  • IntlNumberRangeFormatter::createFromSkeleton(): Argument #2 ($locale) must be no longer than 156 characters

Alternatives

  • Use a locale identifier no longer than ICU’s maximum locale length (156 characters) when calling IntlNumberRangeFormatter::createFromSkeleton().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be odd if argument #1 ($num) is negative

Description

gmp_root() and gmp_rootrem() compute the integer part of the $nth root of $num. A negative number only has a real $nth root when $nth is odd (for example, the cube root of -27 is -3), so an even $nth combined with a negative $num has no meaningful integer result.

This validation has thrown a ValueError since PHP 8.0; PHP 8.6 only corrected the argument name referenced in the message, from the stub’s actual parameter name $num (it previously said $a, which never matched the real signature).

Example

<?php

gmp_root(-27, 4);

?>

Literal Examples

  • gmp_root(): Argument #2 ($nth) must be odd if argument #1 ($num) is negative
  • gmp_rootrem(): Argument #2 ($nth) must be odd if argument #1 ($num) is negative

Alternatives

  • Only request an even $nth root of a negative $num if you actually mean a complex result; otherwise pass a non-negative $num or an odd $nth to gmp_root()/gmp_rootrem().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [PHP 8.0 through 8.5 threw the same ValueError but referenced the first argument as “$a”, which did not match the function’s actual $num parameter name.](PHP 8.0 through 8.5 threw the same ValueError but referenced the first argument as “$a”, which did not match the function’s actual $num parameter name.)

must be of type %s, %s given

Description

This error message reports that the types of the provided arguments are not compatible with the expected types.

Such a conflict appears in various situations:

  • a scalar type is used when another incompatible type is expected: using an array instead of a integer.
  • a compatible type is provided when strict_types is active: for example, using a numeric string or a stringable object with a string type.
  • a parent class is used where a child type is expected: object types accept child classes, not parent ones.
  • the type is an interface, and the provided object is not implementing it explicitly
  • the type has a typo
  • the type should is not the one that is the specifications.

Example

<?php

function foo(int $i) {}
foo([]);
// with strict_types = 1
foo(1.0);

class A {}
class B extends A {}

function goo(B $b) {}
goo(new A);

?>

Literal Examples

  • must be of type Traversable, int given
  • must be of type int, array given
  • must be of type int, float given
  • must be of type A, B given

Alternatives

  • Remove the type.
  • Fix the parameter type.
  • Fix the argument type: convert it to the expected type.

must be of type array when argument #3 ($option) is MCAST_LEAVE_GROUP, %s given

Description

When $option is MCAST_LEAVE_GROUP, socket_set_option() expects $value (argument #4) to be an array (or an object, read as a property bag) describing the group to leave — with keys such as group and interface. Passing anything else, such as the plain string above, is rejected before the request ever reaches the underlying setsockopt() call.

Example

<?php

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

socket_set_option($socket, IPPROTO_IP, MCAST_LEAVE_GROUP, 'not-an-array');

?>

Literal Examples

  • socket_set_option(): Argument #4 ($value) must be of type array when argument #3 ($option) is MCAST_LEAVE_GROUP, string given

Alternatives

  • Pass an array with the group (and, where applicable, interface) keys expected for MCAST_LEAVE_GROUP.
  • Consult the socket_set_option() documentation for the exact shape expected for this option.

In more recent PHP versions, this error message is now :ref:must-be-of-type-array-when-argument-#3-($option)-is-mcast_leave_source_group,-%s-given.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be of type array when argument #3 ($option) is MCAST_LEAVE_SOURCE_GROUP, %s given

Description

When $option is MCAST_LEAVE_SOURCE_GROUP, socket_set_option() expects $value (argument #4) to be an array (or an object, read as a property bag) describing the source-specific multicast group to leave — with keys such as group, source and interface. Passing anything else, such as the plain string above, is rejected before the request ever reaches the underlying setsockopt() call.

Example

<?php

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

socket_set_option($socket, IPPROTO_IP, MCAST_LEAVE_SOURCE_GROUP, 'not-an-array');

?>

Literal Examples

  • socket_set_option(): Argument #4 ($value) must be of type array when argument #3 ($option) is MCAST_LEAVE_SOURCE_GROUP, string given

Alternatives

  • Pass an array with the group, source and interface keys expected for MCAST_LEAVE_SOURCE_GROUP.
  • Consult the socket_set_option() documentation for the exact shape expected for this option.

In previous PHP versions, this error message used to be :ref:must-be-of-type-array-when-argument-#3-($option)-is-mcast_leave_group,-%s-given.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be of type Countable|array, %s given

Description

The count() native function only count elements that are arrays, or objects that implements the Countable interface. Anything else yields a fatal error.

Example

<?php

$value = null;
echo count($value);

?>

Alternatives

  • Check for type before using count: is_array or instanceof \Countable.

In previous PHP versions, this error message used to be :ref:parameter-must-be-an-array-or-an-object-that-implements-countable.

must be of type string when argument #3 ($option) is FIL_ATTACH or FIL_DETACH, %s given

Description

FIL_ATTACH and FIL_DETACH (used with the SOL_FILTER level, on platforms that support BSD accept/receive filters) name the filter to attach or detach as a string. socket_set_option() requires $value (argument #4) to be a string for these two options; any other type, such as the integer above, is rejected.

Example

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_FILTER);

socket_set_option($socket, SOL_FILTER, FIL_ATTACH, 123);

?>

Literal Examples

  • socket_set_option(): Argument #4 ($value) must be of type string when argument #3 ($option) is FIL_ATTACH or FIL_DETACH, int given

Alternatives

  • Pass the filter name as a string.
  • Consult your platform’s setsockopt(2)/SOL_FILTER documentation for valid filter names.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be of type string when argument #3 ($option) is SO_ACCEPTFILTER, %s given

Description

SO_ACCEPTFILTER (available on BSD-derived systems such as FreeBSD) names an accept filter by a short string, e.g. "dataready". socket_set_option() requires $value (argument #4) to be a string for this option; any other type, such as the integer above, is rejected. Note that the string must also be shorter than the platform’s internal filter-name buffer and must not contain a null byte, which are reported as separate ValueError cases.

Example

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_set_option($socket, SOL_SOCKET, SO_ACCEPTFILTER, 123);

?>

Literal Examples

  • socket_set_option(): Argument #4 ($value) must be of type string when argument #3 ($option) is SO_ACCEPTFILTER, int given

Alternatives

  • Pass the accept filter name as a short string, without embedded null bytes.
  • Consult your platform’s accf(9)/setsockopt(2) documentation for valid filter names.

In more recent PHP versions, this error message is now :ref:must-be-of-type-string-when-argument-#3-($option)-is-so_bindtodevice,-%s-given.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be of type string when argument #3 ($option) is SO_BINDTODEVICE, %s given

Description

SO_BINDTODEVICE (Linux) binds a socket to a specific network interface, identified by its name, e.g. "eth0". socket_set_option() requires $value (argument #4) to be a string for this option; any other type, such as the integer above, is rejected.

Example

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_set_option($socket, SOL_SOCKET, SO_BINDTODEVICE, 123);

?>

Literal Examples

  • socket_set_option(): Argument #4 ($value) must be of type string when argument #3 ($option) is SO_BINDTODEVICE, int given

Alternatives

  • Pass the network interface name as a string.
  • Use php_uname() or /sys/class/net to discover the correct interface name if unsure.

In previous PHP versions, this error message used to be :ref:must-be-of-type-string-when-argument-#3-($option)-is-so_acceptfilter,-%s-given. In more recent PHP versions, this error message is now :ref:must-be-of-type-string-when-argument-#3-($option)-is-tcp_congestion,-%s-given.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be of type string when argument #3 ($option) is TCP_CONGESTION, %s given

Description

TCP_CONGESTION selects the congestion-control algorithm for a TCP socket, by name, e.g. "cubic" or "bbr". socket_set_option() requires $value (argument #4) to be a string for this option; any other type, such as the integer above, is rejected.

Example

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_set_option($socket, IPPROTO_TCP, TCP_CONGESTION, 123);

?>

Literal Examples

  • socket_set_option(): Argument #4 ($value) must be of type string when argument #3 ($option) is TCP_CONGESTION, int given

Alternatives

  • Pass the congestion-control algorithm name as a string.
  • List available algorithms via /proc/sys/net/ipv4/tcp_available_congestion_control on Linux.

In previous PHP versions, this error message used to be :ref:must-be-of-type-string-when-argument-#3-($option)-is-so_bindtodevice,-%s-given. In more recent PHP versions, this error message is now :ref:must-be-of-type-string-when-argument-#3-($option)-is-tcp_function_blk,-%s-given.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be of type string when argument #3 ($option) is TCP_FUNCTION_BLK, %s given

Description

TCP_FUNCTION_BLK (FreeBSD only) selects the pluggable TCP stack to use for a connection, identified by its name. socket_set_option() requires $value (argument #4) to be a string for this option; any other type, such as the integer above, is rejected. The string must also be free of null bytes and shorter than the platform’s TCP_FUNCTION_NAME_LEN_MAX, which are reported as separate ValueError cases.

Example

<?php

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_set_option($socket, IPPROTO_TCP, TCP_FUNCTION_BLK, 123);

?>

Literal Examples

  • socket_set_option(): Argument #4 ($value) must be of type string when argument #3 ($option) is TCP_FUNCTION_BLK, int given

Alternatives

  • Pass the TCP stack name as a string, without embedded null bytes.
  • List available stacks via net.inet.tcp.functions_available on FreeBSD.

In previous PHP versions, this error message used to be :ref:must-be-of-type-string-when-argument-#3-($option)-is-tcp_congestion,-%s-given.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH

Description

array_filter() uses its third argument, $mode, to decide what the callback receives: the value (ARRAY_FILTER_USE_VALUE, the default), the key (ARRAY_FILTER_USE_KEY), or both (ARRAY_FILTER_USE_BOTH). No other mode makes sense, since the callback’s signature is chosen based on exactly one of these three constants.

Before PHP 8.6, passing any other integer for $mode was silently treated as ARRAY_FILTER_USE_VALUE. As of PHP 8.6, an unrecognized mode now throws a ValueError instead of falling back silently.

Example

<?php

$array = ['a' => 1, 'b' => 2];

array_filter($array, fn($v) => $v > 0, 42);

?>

Literal Examples

  • array_filter(): Argument #3 ($mode) must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH

Alternatives

  • Pass one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH as the $mode argument to array_filter().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, any unrecognized $mode value was silently treated as ARRAY_FILTER_USE_VALUE.](Previously, any unrecognized $mode value was silently treated as ARRAY_FILTER_USE_VALUE.)

must be one of IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, ::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, ::IDENTITY_FALLBACK_APPROXIMATELY, or ::IDENTITY_FALLBACK_RANGE

Description

IntlNumberRangeFormatter::createFromSkeleton() builds a formatter for numeric ranges (such as 3-5). Its identityFallback argument tells ICU what to do when the range’s start and end turn out to be identical after formatting, and only four such fallback strategies exist: IDENTITY_FALLBACK_SINGLE_VALUE, IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IDENTITY_FALLBACK_APPROXIMATELY, and IDENTITY_FALLBACK_RANGE.

Passing any other integer raises a ValueError, since ICU’s range formatter has no other identity-fallback behavior to fall back to.

Example

<?php

IntlNumberRangeFormatter::createFromSkeleton(
    '',
    'en',
    IntlNumberRangeFormatter::COLLAPSE_AUTO,
    999
);

?>

Literal Examples

  • IntlNumberRangeFormatter::createFromSkeleton(): Argument #4 ($identityFallback) must be one of IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, IntlNumberRangeFormatter::IDENTITY_FALLBACK_APPROXIMATELY, or IntlNumberRangeFormatter::IDENTITY_FALLBACK_RANGE

Alternatives

  • Pass one of IntlNumberRangeFormatter::IDENTITY_FALLBACK_SINGLE_VALUE, ::IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, ::IDENTITY_FALLBACK_APPROXIMATELY, or ::IDENTITY_FALLBACK_RANGE as the identityFallback argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be one of PGSQL_ASSOC, PGSQL_NUM, or PGSQL_BOTH

Description

pg_fetch_all() 2nd argument must be one of 3 possible pgsql constants: PGSQL_ASSOC, PGSQL_NUM and PGSQL_BOTH.

It is also the case of pg_fetch_array() and pg_fetch_row()’s 3rd argument; and pg_select()’s 4th argument.

It is possible to use raw integers, instead of the constants, although this is not recommended.

Example

<?php

try {
    var_dump(pg_last_notice($db, 99));
} catch (\ValueError $e) {
    echo $e->getMessage() . \PHP_EOL;
}

?>

Alternatives

  • Use one of the three constants.

must be one of PGSQL_NOTICE_LAST, PGSQL_NOTICE_ALL, or PGSQL_NOTICE_CLEAR

Description

pg_last_notice() 2nd argument must be one of 3 possible pgsql constants: PGSQL_NOTICE_LAST, PGSQL_NOTICE_ALL, or PGSQL_NOTICE_CLEAR.

It is possible to use raw integers, instead of the constants, although this is not recommended.

Example

<?php

try {
    var_dump(pg_last_notice($db, 99));
} catch (\ValueError $e) {
    echo $e->getMessage() . \PHP_EOL;
}

?>

Alternatives

  • Use one of the three constants.

must be one of the PATHINFO_* constants

Description

pathinfo() takes an optional $flags argument built from the PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION, PATHINFO_FILENAME, and PATHINFO_ALL constants, describing which parts of the path to return.

Previously, passing a value outside this set was silently accepted and produced an empty (or nonsensical) result. As of PHP 8.6, pathinfo() validates that $flags is actually built from these constants and throws a ValueError otherwise, instead of silently returning incomplete information.

Example

<?php

pathinfo('/tmp/example.txt', 9999);

?>

Literal Examples

  • pathinfo(): Argument #2 ($flags) must be one of the PATHINFO_* constants

Alternatives

  • Only pass a combination of PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION, PATHINFO_FILENAME, or PATHINFO_ALL as the $flags argument.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, an invalid $flags value was silently accepted and returned incomplete or empty results instead of throwing.](Previously, an invalid $flags value was silently accepted and returned incomplete or empty results instead of throwing.)

must be one of the SCANDIR_SORT_ASCENDING, SCANDIR_SORT_DESCENDING, or SCANDIR_SORT_NONE constants

Description

scandir() takes an optional $sorting_order argument controlling how the returned directory listing is sorted: SCANDIR_SORT_ASCENDING (the default), SCANDIR_SORT_DESCENDING, or SCANDIR_SORT_NONE.

Before PHP 8.6, passing any other integer silently fell through to one of these behaviors without warning. As of PHP 8.6, an unrecognized sorting order now throws a ValueError naming the offending argument.

Example

<?php

scandir('/tmp', 42);

?>

Literal Examples

  • scandir(): Argument #2 ($sorting_order) must be one of the SCANDIR_SORT_ASCENDING, SCANDIR_SORT_DESCENDING, or SCANDIR_SORT_NONE constants

Alternatives

  • Pass one of SCANDIR_SORT_ASCENDING, SCANDIR_SORT_DESCENDING, or SCANDIR_SORT_NONE as the $sorting_order argument to scandir().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, an unrecognized $sorting_order value was silently accepted instead of throwing.](Previously, an unrecognized $sorting_order value was silently accepted instead of throwing.)

must be only one of the PATHINFO_* constants

Description

Unlike most bitmask arguments, pathinfo()’s $flags argument (aside from the catch-all PATHINFO_ALL) is meant to select exactly one part of the path at a time: PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION, or PATHINFO_FILENAME. Combining two of them with | does not make sense, since the function then wouldn’t know which single value to return.

As of PHP 8.6, combining more than one of these single-part constants (without using PATHINFO_ALL) throws a ValueError, instead of silently returning just one of the requested parts.

Example

<?php

pathinfo('/tmp/example.txt', PATHINFO_DIRNAME | PATHINFO_EXTENSION);

?>

Literal Examples

  • pathinfo(): Argument #2 ($flags) must be only one of the PATHINFO_* constants

Alternatives

  • Pass exactly one of PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION, or PATHINFO_FILENAME, or use PATHINFO_ALL to get all of them as an array.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, combining multiple single-part PATHINFO_* constants silently returned only one of the requested parts instead of throwing.](Previously, combining multiple single-part PATHINFO_* constants silently returned only one of the requested parts instead of throwing.)

must be OPENSSL_ENCODING_DER or OPENSSL_ENCODING_PEM

Description

PHP 8.6 introduces Openssl\Session, a class representing a TLS session that can be exported and later re-imported to resume a connection without a full handshake. Both Openssl\Session::export() and the static Openssl\Session::import() take a $format argument describing how the session data is encoded, but only two encodings are supported: OPENSSL_ENCODING_DER and OPENSSL_ENCODING_PEM.

Passing any other integer as the format raises a ValueError, since there is no other encoding these methods know how to produce or parse.

Example

<?php

$session = Openssl\Session::import('previously-exported-session-data', 999);

?>

Literal Examples

  • Openssl\Session::import(): Argument #2 ($format) must be OPENSSL_ENCODING_DER or OPENSSL_ENCODING_PEM

Alternatives

  • Pass either OPENSSL_ENCODING_DER or OPENSSL_ENCODING_PEM as the $format argument to Openssl\Session::export() or Openssl\Session::import().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be smaller than or equal to argument #3 ($max)

Description

PHP 8.6 introduces the clamp() function, which returns $value restricted to the inclusive range [$min, $max]. For that range to mean anything, $min must not be greater than $max.

Passing a $min that is greater than $max throws a ValueError for the second argument, naming $max as the argument it must not exceed, instead of silently returning a nonsensical result.

Example

<?php

clamp(5, 10, 1);

?>

Literal Examples

  • clamp(): Argument #2 ($min) must be smaller than or equal to argument #3 ($max)

Alternatives

  • Make sure the $min argument to clamp() is not greater than $max; swap them if they were passed in the wrong order.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be SODIUM_CRYPTO_PWHASH_SALTBYTES bytes long

Description

sodium_crypto_pwhash() derives a key from a password using Argon2i, and it needs a salt as its third argument. The salt must be exactly SODIUM_CRYPTO_PWHASH_SALTBYTES bytes long, which is 16 bytes. Any other length throws a SodiumException.

The salt should be random and unique for each password. Generate it with random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES), and store it next to the derived key, since the same salt is needed to derive the key again.

Example

<?php

// The salt must be exactly SODIUM_CRYPTO_PWHASH_SALTBYTES (16) bytes long
$key = sodium_crypto_pwhash(
    16,
    'password',
    'short',
    SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
    SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);

?>

Literal Examples

  • sodium_crypto_pwhash(): Argument #3 ($salt) must be SODIUM_CRYPTO_PWHASH_SALTBYTES bytes long

Alternatives

  • Generate the salt with random_bytes(SODIUM_CRYPTO_PWHASH_SALTBYTES), so its length always matches.
  • If you do not need to manage the salt yourself, use sodium_crypto_pwhash_str(). It creates the salt and stores it inside the returned hash string.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must be SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES bytes long

Description

sodium_crypto_pwhash_scryptsalsa208sha256() derives a key from a password using the scrypt algorithm, and it needs a salt as its third argument. The salt must be exactly SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES bytes long, which is 32 bytes. Any other length throws a SodiumException.

This constant is different from SODIUM_CRYPTO_PWHASH_SALTBYTES, which is used by sodium_crypto_pwhash(). A salt that works with one function does not necessarily work with the other.

The salt should be random and unique for each password. Generate it with random_bytes(SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES), and store it with the derived key.

Example

<?php

// The salt must be exactly SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES (32) bytes long
$key = sodium_crypto_pwhash_scryptsalsa208sha256(
    16,
    'password',
    'short',
    SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE,
    SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE
);

?>

Literal Examples

  • sodium_crypto_pwhash_scryptsalsa208sha256(): Argument #3 ($salt) must be SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES bytes long

Alternatives

  • Generate the salt with random_bytes(SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES), so its length always matches.
  • Check that the constant matches the function: use SODIUM_CRYPTO_PWHASH_SALTBYTES with sodium_crypto_pwhash(), and this constant with sodium_crypto_pwhash_scryptsalsa208sha256().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must contain a type for object ID %s

Description

SNMP::set() lets $objectId, $type, and $value each be passed as parallel arrays, matched up element by element. Every object ID in $objectId needs a corresponding entry in $type describing what kind of SNMP value is being set.

If $type runs out of elements before $objectId does, the object ID that has no matching type now throws a ValueError naming that OID, instead of silently skipping it with a warning.

Example

<?php

$snmp = new SNMP(SNMP::VERSION_2c, 'localhost', 'private');

$snmp->set(
    ['.1.3.6.1.2.1.1.6.0'],
    [],
    ['New location']
);

?>

Literal Examples

  • SNMP::set(): Argument #2 ($type) must contain a type for object ID ‘.1.3.6.1.2.1.1.6.0’

Alternatives

  • Make sure the $type array passed to SNMP::set() has one entry for every object ID in $objectId.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, this emitted an E_WARNING (“‘%s’: no type set”) and silently skipped the affected object ID, instead of throwing.](Previously, this emitted an E_WARNING (“‘%s’: no type set”) and silently skipped the affected object ID, instead of throwing.)

must contain a value for object ID %s

Description

SNMP::set() lets $objectId, $type, and $value each be passed as parallel arrays, matched up element by element. Every object ID in $objectId needs a corresponding entry in $value describing what to set it to.

If $value runs out of elements before $objectId does, the object ID that has no matching value now throws a ValueError naming that OID, instead of silently skipping it with a warning.

Example

<?php

$snmp = new SNMP(SNMP::VERSION_2c, 'localhost', 'private');

$snmp->set(
    ['.1.3.6.1.2.1.1.6.0'],
    ['s'],
    []
);

?>

Literal Examples

  • SNMP::set(): Argument #3 ($value) must contain a value for object ID ‘.1.3.6.1.2.1.1.6.0’

Alternatives

  • Make sure the $value array passed to SNMP::set() has one entry for every object ID in $objectId.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, this emitted an E_WARNING (“‘%s’: no value set”) and silently skipped the affected object ID, instead of throwing.](Previously, this emitted an E_WARNING (“‘%s’: no value set”) and silently skipped the affected object ID, instead of throwing.)

must contain at least one element

Description

min() and max() only work on arrays that contains at least one element. The object here is to avoid the confusion of the null value that may be the result of the operation, and the null that PHP used to return when there was nothing to process in the array.

Example

<?php

echo min([]);
echo max([]);

?>

Alternatives

  • Check for empty() before using the min() or max() functions.

must have a length less than or equal to %u

Description

bzdecompress() hands its input off to libbzip2, which tracks buffer sizes in a 32-bit unsigned integer internally. A $data string of 4294967296 bytes (2^32) or more cannot be represented by that counter and would silently overflow.

As of PHP 8.6, bzdecompress() rejects oversized input up front with a ValueError, instead of risking an integer overflow while decompressing it.

Example

<?php

$data = str_repeat('a', 4294967296);

bzdecompress($data);

?>

Literal Examples

  • bzdecompress(): Argument #1 ($source) must have a length less than or equal to 4294967295

Alternatives

  • Do not pass strings close to or larger than 4 GB to bzdecompress(); decompress the data in smaller chunks instead if possible.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, oversized input could trigger an unsigned integer overflow inside bzdecompress() instead of being rejected.](Previously, oversized input could trigger an unsigned integer overflow inside bzdecompress() instead of being rejected.)

must not be empty, use str_split() to split a string into characters

Description

explode() splits a string on every occurrence of a $separator. An empty separator has no well-defined meaning for that operation, so it has always been rejected.

As of PHP 8.6, the ValueError message for this case was made more actionable: instead of just saying the separator cannot be empty, it now points directly to str_split(), which is the correct tool for splitting a string into its individual characters.

Example

<?php

explode('', 'hello');

?>

Literal Examples

  • explode(): Argument #1 ($separator) must not be empty, use str_split() to split a string into characters

Alternatives

  • Use str_split() instead of explode('', ...) to split a string into individual characters.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, this was reported as “explode(): Argument #1 ($separator) cannot be empty”, without the str_split() suggestion.](Previously, this was reported as “explode(): Argument #1 ($separator) cannot be empty”, without the str_split() suggestion.)

must not be empty when passed as an array

Description

SNMP::get(), ::getnext(), ::walk(), and ::set() accept $objectId as either a single string or an array of object IDs. An empty array carries no object IDs at all, so there is nothing for the query to operate on.

As of PHP 8.6, passing an empty array throws a ValueError, instead of the extension emitting a global error and returning false without saying which argument was the problem.

Example

<?php

$snmp = new SNMP(SNMP::VERSION_2c, 'localhost', 'public');

$snmp->get([]);

?>

Literal Examples

  • SNMP::get(): Argument #1 ($objectId) must not be empty when passed as an array
  • SNMP::set(): Argument #1 ($objectId) must not be empty when passed as an array

Alternatives

  • Pass at least one object ID, either as a string or as a non-empty array, to SNMP::get()/getnext()/walk()/set().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, this threw a generic ValueError (“Array of object IDs must not be empty”) that did not name the affected argument.](Previously, this threw a generic ValueError (“Array of object IDs must not be empty”) that did not name the affected argument.)

must not be empty

Description

The provided parameter is of the valid type, but cannot be left empty.

Example

<?php

print_r(explode('', 'abc')); // Not possible with an empty delimiter

print_r(str_split(1, 'abc')); 

?>

Alternatives

  • When parsing data, make sure that the separator is not empty.

In previous PHP versions, this error message used to be :ref:cannot-be-empty.

must not be NAN

Description

PHP 8.6’s clamp() function returns $value restricted to the range [$min, $max]. Comparing anything against NAN never produces a meaningful ordering, so $min and $max cannot be NAN.

Passing NAN as either bound throws a ValueError naming the offending argument, instead of returning an unpredictable result.

Example

<?php

clamp(5, NAN, 10);

?>

Literal Examples

  • clamp(): Argument #2 ($min) must not be NAN
  • clamp(): Argument #3 ($max) must not be NAN

Alternatives

  • Do not pass NAN as the $min or $max argument to clamp(); validate floating-point bounds with is_nan() first if they come from an untrusted source.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

must not contain empty strings

Description

The deflate_init() function accepts options. Among the options, there is a dictionary, with a dictionary of preset strings. Theses strings cannot be left empty.

Before PHP 8.2, this bug would crash PHP.

Example

<?php
try {
    deflate_init(ZLIB_ENCODING_DEFLATE, [dictionary => [, ]]);
} catch (ValueError $ex) {
    echo $ex->getMessage(), \n;
}
?>

Alternatives

  • Remove the 2nd argument.
  • Remove the ‘dictionary’ entry in the 2nd argument.
  • Put an actual value in the values of the ‘dictionary’ entry in the 2nd argument.

must not exceed %d bytes

Description

PHP 8.6 introduces Openssl\Psk, which holds a pre-shared key (and an optional identity) used to authenticate TLS connections without a certificate. OpenSSL itself imposes fixed limits on both fields: a PSK cannot exceed Openssl\Psk::MAX_PSK_LEN (256) bytes, and an identity cannot exceed Openssl\Psk::MAX_IDENTITY_LEN (128) bytes.

Passing a longer string to Openssl\Psk::__construct() throws a ValueError for the offending argument instead of silently truncating the key or identity.

Example

<?php

$psk = new Openssl\Psk(str_repeat('a', 300));

?>

Literal Examples

  • Openssl\Psk::__construct(): Argument #1 ($psk) must not exceed 256 bytes

Alternatives

  • Keep the pre-shared key to 256 bytes or fewer, and the identity to 128 bytes or fewer.
  • Use Openssl\Psk::MAX_PSK_LEN and Openssl\Psk::MAX_IDENTITY_LEN to validate lengths before constructing the object.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Must not use parent::$%s::%s() in a different property ($%s)

Description

Property hooks are actual methods: they can call other methods to fulfill their mission. They may also call the parent’ methods, and, as such, they may also call the parent’s property hook. This has lead to the syntax parent::$properpty::get().

This syntax is specific to property hooks, and can only be used inside the same property hook for the same property.

Example

<?php

class X {
    public string $q { 
        get => 'in parent';
    }
}

class Y extends X {
    public string $property { 
        // Must not use parent::$q::get() in a different property ($property)
        get => parent::$q::get();
    }
}

$y = new Y;
echo $y->q;

?>

Literal Examples

  • Must not use parent::$q::get() in a different property ($p)

Alternatives

  • Move the block of the property hook in a regular method and call it from the hook and other methods.
  • Inline the code every time it is needed.

Must not use parent::$%s::%s() in a different property hook (%s)

Description

Property hooks are actual methods: they can call other methods to fulfill their mission. They may also call the parent’ methods, and, as such, they may also call the parent’s property hook. This has lead to the syntax parent::$properpty::get().

This syntax is specific to property hooks, and can only be used inside the same property hook for the same property.

Example

<?php

class X {
    public string $q { 
        get => 'in parent';
    }
}

class Y extends X {
    public string $q { 
        // Must not use parent::$q::get() in a different property hook ($p)
        set => parent::$q::get();
    }
}

$y = new Y;
echo $y->q;

?>

Literal Examples

  • Must not use parent::$q::get() in a different property hook ($p)

Alternatives

  • Move the block of the property hook in a regular method and call it from the hook and other methods.
  • Inline the code every time it is needed.

Must not use parent::$%s::%s() outside a property hook

Description

Property hooks are actual methods: they can call other methods to fulfill their mission. They may also call the parent’ methods, and, as such, they may also call the parent’s property hook. This has lead to the syntax parent::$properpty::get().

This syntax is specific to property hooks, and can only be used inside the same property hook for the same property.

Example

<?php

class X {
    public string $q { 
        get => 'in parent';
    }
}

class Y extends X {
    public string $q { 
        get => parent::$q::get();
    }
    
    function foo(): string {
        // Must not use parent::$q::get() outside a property hook
        return parent::$q::get();
    }
}

$objectY = new X;
echo $objectY->q;

?>

Literal Examples

  • Must not use parent::$q::get() outside a property hook

Alternatives

  • Move the block of the property hook in a regular method and call it from the hook and other methods.
  • Inline the code every time it is needed.

Named parameter $%s overwrites previous argument

Description

Named parameter and positional arguments are setting the same argument, with different name. PHP reports this to avoid overwritting the first with the second.

In the first example, there are two cases for this error: either a repetition of the same parameter in the argument list, or a mix of positional and named parameters, which leads to the second overwriting the first.

In the second example, a mix of named and positionned arguments is used, and there is a duplicate for the

There is a distinct error message when this happens to in attributes calls.

Example

<?php

function foo($a, $b) { print_r($b); }

foo(a: 1, a:1);
foo(1, a:1);

// 1 is given to $a, by its position 0
// 2 is given to $a, by its name 'a'. This is a conflict
$args = [1, a => 2];
foo(...$args); // error

$args = [a => 1, 2];
foo(...$args); // Cannot use positional argument after named argument during unpacking

$args = [b => 1];
foo(...$args, b: 2); // b is overwritten

?>

Literal Examples

  • Named parameter $a overwrites previous argument

Alternatives

  • Remove duplicate named parameters in the argument list.
  • Add all names to parameters in the argument list.
  • Remove all names to parameters in the argument list.

namespace%s is an invalid class name

Description

This is the unquoted counterpart of the 'namespace\%s' is an invalid class name error: it carries the exact same runtime message, just without the surrounding single quotes PHP actually prints around the offending name.

namespace used at the start of a fully qualified name refers to the current namespace, and is usually omitted. self describes the current class: it is a relative class name with no absolute-path equivalent, so writing it as namespace\self (or the equivalent \self) is meaningless and rejected. The same applies to static and parent.

Example

<?php

function foo(namespace\self $a) {};

function foo( $a): namespace\self {};

class X {
    private namespace\self $f;
    private namespace\x $f2;
}

?>

Literal Examples

  • namespace\self is an invalid class name

Alternatives

  • Remove the initial namespace and backslash.
  • Use the literal name of the intended class.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Namespace declaration statement has to be

Description

A namespace declaration must be the very first statement of the file, or immediately follow a declare() call (such as declare(strict_types=1);). Any other statement, including a simple echo, a comment that generates output, or whitespace before the opening <?php tag, placed before the namespace statement makes it invalid.

The full message reads: Namespace declaration statement has to be the very first statement or after any declare call in the script.

Example

<?php

echo 'Hello';

namespace App;

?>

Literal Examples

  • Namespace declaration statement has to be the very first statement or after any declare call in the script

Alternatives

  • Move the namespace statement to be the first statement in the file, right after the opening <?php tag.
  • Only keep a declare() call before the namespace statement, and move everything else after it.
  • Remove any whitespace or output before the opening <?php tag.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Namespace declarations cannot be nested

Description

Namespace declaration, with blocks, cannot be nested one into the other. Namespaces must be one next to each other.

Usually, there is only one namespace per file, without a block.

Example

<?php

namespace A {
    namespace B {
    
    }
}

?>

Alternatives

  • Make the namespaces next to each other; concatenate the names to create deep namespaces: namespace A\B {..}.
  • Split the code into several files, each with only one namespace.

needle is not a string or an integer

Description

The second argument may be a string, or an integer, which will be used as a string. Any other type is forbidden, in particular array. Other types may yield other error messages, such as a type error.

Example

<?php

print strpos('abc99', []);

?>

Alternatives

  • Use a foreach on an array of strings, and use these values instead.
  • Pick up a value in the array.

Negative power of zero

Description

It is not possible to calculate a negative power of 0: a negative power is, in fact, a division raised to a power, and division by zero is undefined.

It was a silent error until PHP 8.4, and it is now a visible one.

This is also the case with PHP native ** and pow().

Example

<?php

echo bcpow(0, -1); 

?>

Alternatives

  • Check for the first argument not to be 0, or similar.
  • Catch the exception.

Nesting level too deep - recursive dependency?

Description

PHP comparison may be recursive: it happens when an array contains a reference to another element of itself. In that case, the array becomes recursive: traversing such array may end up with an infinite loop, as the reference may loop back on itself.

This error message applies to array comparisons, and count(). There might be other situations where this applies.

Example

<?php

$a = [1, 5=> &$a];
$b = [1, 5=> &$b];

try {
    var_dump($a === $b);
} catch (Error $e) {
    print caught\n;
}

// count() doesn't handle recursive arrays
count($a);

?>

Alternatives

  • Do not make direct comparisons of recursive arrays.
  • Do not try to count recursive arrays.

never can only be used as a standalone type

Description

never is a special return type, indicating that a function or method never returns control to its caller: it always throws, calls exit(), or otherwise never completes normally.

Because never represents the absence of any return at all, it cannot be combined with other types in a union, nor made nullable: it can only be used on its own, as the sole return type of a function or method.

Example

<?php

function foo(): int|never {}

?>

Alternatives

  • Remove the other types, and use never alone.
  • Remove never, and keep the other type(s) alone.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

never cannot be used as a parameter type

Description

Never is a PHP return type, that is used to indicate that a method will not return a value. As such, it makes no sense to use with a parameter, as a parameter cannot return any value. Hence, the never type cannot be used with a parameter.

Example

<?php

function foo(never $n) {}

?>

Alternatives

  • Remove the never type.
  • Change the never type to another type.

never-returning function must not implicitly return

Description

A never returning function or method never reaches the end of the method, or any return operation. It must either throw an exception, trigger an error, die or exit, or stay in an infinite loop.

In the case of an empty function, PHP execution reachs the end of the method, and adds an implicit return null call, which triggers the TypeError.

never type is checked at execution time, though the presence of return in the body of the method triggers it at linting time.

Example

<?php

function foo() : never { }

?>

Alternatives

  • Remove all return calls from the body of the method.
  • Prevent the method to reaching its end.
  • Checks that the method include either a throw, die or exit, a call to another never-returning method, or an infinite loop.

New expressions are not supported in this context

Description

It is not possible to use directly an object as value for a class constant.

It is also not allowed to use an object as default value for properties, static or not.

On the other hand, it is possible to use an object stored in a global constant. And, since it is possible to use a global constant as a value for a class constant, it is easy to work around this limitation. The same trick is possible with properties, as long as the target object is not self.

Properties cannot use their host class as default values: it leads to a chicken and egg problem. The global constant must be created with an object of the class, which is then immediately instantiated with a default value based on the global constant.

Example

<?php

class B {}

const CONSTANT_B = new B;

class X {
	// This is not possible
	const A = new B;

	// This is possible, with the same result
	const A2 = CONSTANT_B;
}

?>

Alternatives

  • Remove the constant A.
  • Create a global constant, and assign it to A.
  • Make the constant a property.
  • Create a global constant, and assign it to the class constant.

No code may exist outside of namespace

Description

When using a block notation for namespaces, there cannot be any other code outside the namespaced blocks. Here, the function foo() is outside the namespace block.

The error message is not strictly true: the declare command may be left out of the namespace, and so does any comments.

Example

<?php

namespace A {

}

function foo() {}

?>

Alternatives

  • Move all the code inside a namespace block.
  • For global namespace, use the namespace {...} command without a name.
  • Switch to the namespace command without block: all the code will be in that namespace, until the next namespace command.

No ending delimiter ‘%c’ found

Description

This error is a regex related error, not a PHP one. The regular expression is the first argument of the call. It is invalid, as regex are supposed to start and end with the same non-alphanumeric character.

Then, PHP stops the process, and returns false. In this case, false may be confused with a failure to find the pattern in the string, and yield unexpected results.

Example

<?php

preg_match('/[a-b]', 'abc');

?>

Literal Examples

  • No ending delimiter ‘/’ found

Alternatives

  • Fix the regex.

No such file or directory

Description

PHP reports, as warning, a failure to remove a file that doesn’t exists. This is both an error, as the file could not be removed, but also a success, as the file is removed in the end.

Example

<?php

unlink(non-existing-file.txt);

?>

Literal Examples

  • unlink(oops): No such file or directory

Alternatives

  • Check that the file exists before trying to remove it.

Non-abstract method %s::%s() must contain body

Description

A method must have a body block. When it has no body block, it has a semicolon instead, and it must have the abstract keyword for the method, and following, to the class.

Example

<?php

class X {
     function foo();
}

?>

Literal Examples

  • Non-abstract method X::foo() must contain body

Alternatives

  • Add a body block to the method.
  • Add a abstract option to the method and to the class.

Non-abstract property hook must have a body

Description

Property hooks, both set and get, may be made abstract by replacing the body block by a semi-colon. And, just like methods, property hooks must use the abstract property, although the property definition has to support the option, not the property hook itself.

Example

<?php

class X {
	// This is an error. A property hook must have a body
    public $property {
        get;
    }

	// This is OK. The property is marked as abstract
    public abstract $abstractProperty {
        get;
    }
}

?>

Alternatives

  • Add a body to the property hook.
  • Add the abstract keyword to the property definition.

Non-canonical cast (binary) is deprecated, use the (string) cast instead

Description

The non-canonical cast (binary) has been deprecated. It should be replace by the simpler (string).

Example

<?php

$a = (binary) $string;

?>

Alternatives

  • Use (string).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See nonCanonicalCast

Non-canonical cast (boolean) is deprecated, use the (bool) cast instead

Description

The non-canonical cast (boolean) has been deprecated. It should be replace by the simpler (bool).

Example

<?php

$a = (boolean) $string;

?>

Alternatives

  • Use (bool).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See nonCanonicalCast

Non-canonical cast (double) is deprecated, use the (float) cast instead

Description

The non-canonical cast (double) has been deprecated. It should be replace by the simpler (float).

Example

<?php

$a = (double) $string;

?>

Alternatives

  • Use (float).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See nonCanonicalCast

Non-canonical cast (integer) is deprecated, use the (int) cast instead

Description

The non-canonical cast (integer) has been deprecated. It should be replace by the simpler (int).

Example

<?php

$a = (integer) $string;

?>

Alternatives

  • Use (int).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See nonCanonicalCast

Non-enum class %s cannot implement interface %s

Description

UnitEnum is an PHP native and reserved interface. It is only used with enumerations. It is also handled by PHP itself, which adds it to enumerations: there is no need to add it explictly. This applies to BackedEnum and UnitEnum, as of PHP 8.4.

Example

<?php

    class X implements YnitEnum {}

?>

Literal Examples

  • Non-enum class x cannot implement interface UnitEnum
  • Non-enum class x cannot implement interface BackEnum

Alternatives

  • Turn the class into an enumeration.
  • Remove the UnitEnum implementation.

Non-readonly class %s cannot extend readonly class %s

Description

A readonly class cannot extends a non-readonly class; a non-readonly class cannot extends a readonly class. Both classes must be readonly or non-readonly to be able to extends one another. This is due to readonly being applied to all available properties, which is ambiguous with class hierarchies.

Example

<?php

readonly class Foo
{
}

class Bar extends Foo
{
}

?>

Literal Examples

  • Non-readonly class Foo cannot extend readonly class Bar

Alternatives

  • Make both classes readonly.
  • Make both classes non-readonly.
  • Make both classes non-readonly and apply readonly per properties.

Non-static method %s::%s() cannot be called statically

Description

While a non-static method can call a static method, the contrary is not possible. In particular, the non-static method will not be able to have a valid $this variable, since the static call doesn’t provide one.

This error is also reported when creating a closure from a non-static method. This happen even if the method is not actually called.

Example

<?php

class X {
    static function foo() {
        //Non-static method x::foo() cannot be called statically
        self::goo();
    }
    
    function goo() {}
}

(new X)->foo();

// when creating a closure
$closure = X::goo(...);

?>

Literal Examples

  • Non-static method x::foo() cannot be called statically

Alternatives

  • Make the concrete method static too.
  • Find an object to call the non-static method.

In previous PHP versions, this error message used to be :ref:non-static-method-%s::%s()-should-not-be-called-statically.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See nonStaticMethodCalledStatically

Non-static method %s::%s() should not be called statically

Description

A non-static method requires an object to be called, as PHP will populate that object in the $this method.

If the method makes no use of $this, make it static to allow the call. Otherwise, keep it non-static, and use an object for the call.

Example

<?php

class X {
	function foo() { echo __METHOD__;}
}

X::foo();

?>

Literal Examples

  • Non-static method x::foo() should not be called statically

Alternatives

  • Make the method static.
  • Find an object to call the method.

In more recent PHP versions, this error message is now :ref:non-static-method-%s::%s()-cannot-be-called-statically.

Non-string needles will be interpreted as strings in the future. Use an explicit chr() call to preserve the current behavior

Description

Until PHP 8.0, strpos() accepted integers as second argument. Then, it would automagically, transform them into their equivalent. Hence, it returned 2 in PHP 7.4.

In PHP 8.0 and later, the integer is used as a string. Unless the ASCII characters and the string matches, it would return nothing.

Example

<?php

// 99 is ASCII for c
print strpos('abc99', 99);

// displays 3 in PHP 8.0+
// displays 2 in PHP 7.4-

?>

Alternatives

  • Use chr(99) instead of 99, to ensure the second argument is a string.
  • Convert the second argument into a string first.

null cannot be marked as nullable

Description

Since PHP 8.2, null (like false and true) can be used directly as a standalone type. But null already means exactly one thing: the value null. Marking it nullable with a leading ?, as in ?null, would only mean null or null, which is entirely redundant, so PHP rejects it.

Example

<?php

function test(): ?null
{
}

?>

Literal Examples

  • null cannot be marked as nullable

Alternatives

  • Remove the ? and use null on its own.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Object %s#%d not contained in WeakMap

Description

This error is thrown when a WeakMap is read with an object that is not one of its keys. The message gives the class and the object id of the missing key, such as stdClass#2.

Reading a missing key is an error, unlike isset(), which returns false for it. Removing a missing key with unset() does nothing and does not raise this error.

Also note that a key is removed from the WeakMap as soon as the object is destroyed, so reading the map with an object that has already been freed raises this error too.

Example

<?php

$map = new WeakMap();
$object = new stdClass();

// $object was never added to the WeakMap
echo $map[$object];

?>

Literal Examples

  • Object stdClass#2 not contained in WeakMap

Alternatives

  • Check that the key is in the map with isset() before reading it: if (isset($map[$object])) { ... }.
  • Use $map[$object] ?? $default to provide a default value when the key is missing. The ?? operator does not raise the error.
  • Make sure the object was added to the map with $map[$object] = $value before it is read.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Object casts are not supported in this context

Description

All cast operators are not supported in a static constant expression. This applies to all casts operations: (int), (string), (bool), (array), (object), until PHP 8.5. In PHP 8.5 and later, only (object) is not supported.

They look like any other operator, such as + or ., but they require data manipulations which are incompatible with constant expressions.

While it may be useless to apply a cast to a literal value, it might be useful to use it with another expression or another constant.

Example

<?php
class X {
    public $foo = (object) [];
}
?>

Alternatives

  • Create a value directly with the target type.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Object not initialized

Description

This error appears with intl and spl extensions. It happens when an object was not fully initialized with the extension: it was only extended and the parent constructor was omitted. This leaves the custom object valid, but not finalized from the parent point of view.

This error may also happen when the object keeps being used, after an unset() call, or __destructor call.

Example

<?php

class MyDirectoryIterator extends DirectoryIterator {
    public function __construct() {}
}

$it = new MyDirectoryIterator;
try {
    $it->key();
} catch (Error $e) {
    echo $e->getMessage(), \n;
}

?>

Alternatives

  • Call parent::__construct in the custom constructor.
  • Remove any call to the object after destruction.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Object of class %s could not be converted to %s

Description

An object cannot be converted automatically into a string, without calling a dedicated method, or setting up the magic method called __toString.

With native PHP operators and functions, the call to __toString is automagic. With custom functions, it is dependent on the strict_types configuration: when strict_types is activated, it prevents the automatic conversion to string, and yields the error.

Example

<?php

class X {}

$x = new X;
// This would work if the __toString() method is defined in X
echo $x;

function foo(string $s) {
    echo $s;
}

// This works with __toString() and without strict_types=1
foo($x);

?>

Literal Examples

  • Object of class X could not be converted to string

Alternatives

  • Remove the strict_types configuration.
  • Add a cast to (string) to explicitly activate the conversion to string.
  • Create a method to do the conversion, and use it, instead of the raw object.

Object of class %s could not be converted to bool

Description

PHP reports that the object cannot be used as a boolean. Converting an object into a boolean is a PHP engine feature, and should be always on. Though, some extensions have not systematically implemented it.

Here, gmp is lacking the support for converting objects into a boolean, though it was fixed in PHP 8.4. When meeting such error, it should be reported to the author of the extension.

Example

<?php

$x = gmp_result('12', 3);

if ($x) {
    print $x is truthy;
}

?>

Literal Examples

  • Object of class GMP could not be converted to bool

Alternatives

  • Make an explicit comparison, with is_object().
  • Make an explicit comparison, with instanceof.

Object of class %s could not be converted to float

Description

PHP reports that the object cannot be used as an float. Converting an object into a float is only possible when the underlying class has provided the code for it. There is no userland code to do that, such as a magic code: it is only possible via a call to a method that returns a float.

Among the PHP classes, gmp and bcmath (in PHP 8.4) extensions provide classes which also works with math operations. Most of the other classes do not convert easily to numbers, as it makes little sense to convert a database connexion (for example) into a number.

Example

<?php

class Y { }

// Error!
echo new Y + 1; 

$multiplication = gmp_mul('12', 3);

print $multiplication * 4; // 144

$number = new BcMath\Number('1.234');

$addition = $number->add(new BcMath\Number('2.34567'));

print $addition + 1; // 4.57967

?>

Literal Examples

  • Object of class Y could not be converted to float
  • Object of class Mysqli could not be converted to float

Alternatives

  • Implement tod that returns an integer, on that object.
  • Upgrade to PHP 8.4, to use automatic conversion with bcmath.

Object of class %s could not be converted to int

Description

PHP reports that the object cannot be used as an integer. Converting an object into a int is only possible when the underlying class has provided the code for it. There is no userland code to do that, such as a magic code: it is only possible via a call to a method that returns an integer.

Among the PHP classes, gmp and bcmath (in PHP 8.4) extensions provide classes which also works with math operations. Most of the other classes do not convert easily to numbers, as it makes little sense to convert a database connexion (for example) into a number.

Example

<?php

class Y { }

// Error!
echo new Y + 1; 

$multiplication = gmp_mul('12', 3);

print $multiplication * 4; // 144

$number = new BcMath\Number('1.234');

$addition = $number->add(new BcMath\Number('2.34567'));

print $addition + 1; // 4.57967

?>

Literal Examples

  • Object of class Y could not be converted to int
  • Object of class Datetime could not be converted to int

Alternatives

  • Implement tod that returns an integer, on that object.
  • Upgrade to PHP 8.4, to use automatic conversion with bcmath.

Object of class %s could not be converted to string

Description

PHP reports that the object cannot be used as a string. Converting an object into a string is only possible when the magic method __toString() is implemented, or when the interface Stringable is implemented.

In that case, the object is automatically converted into a string, thanks to that method. Otherwise, it is a Fatal error.

This is a distinct error than passing an object in a string argument: in that case, it is a Type error.

A lot of native PHP classes support the conversion, but not all of them. Check for stringable interface before using them.

Example

<?php

class Y { }

//error!
echo (new Y); 

// X could also be implementing Stringable, to enforce the __toString() method
class X {
    function __construct(array $arg) {
        $this->a = $arg;
    }
    
    function __toString(){
        return implode(', ', $this->arg);
    }
}

// valid
echo (new X);

$array1 = [E::A];
$array2 = [E::B];
enum E: string {
    case A = 'a';
    case B = 'b';
}

// hidden necessary string conversion
array_intersect($array1, $array2); // also with other array_intersect* functions

?>

Literal Examples

  • Object of class Y could not be converted to string
  • Object of class stdClass could not be converted to string

Alternatives

  • Implement the Stringable interface on the class, or its parent.
  • Implement the __toString method n the class, or its parent.
  • Call a method that returns a string, on that object.
  • Use print_r or var_dump to get the details inside the object.

Object of type %s has not been correctly initialized by calling parent::__construct() in its constructor

Description

PHP needs an explicit call to the parent constructor to init the parent class. Sometimes, overwritten constructor is an expected features. With PHP native classes, Datetime and Datetimezone must be explicitly called when extended.

Note that this error is only raised when the object is used, and not at instantiation time.

Example

<?php

class X extends DateTime {
	public function __construct() { }
}

$object = new X;
var_dump(object->format("d"));
?>

Literal Examples

  • Object of type X has not been correctly initialized by calling parent::__construct() in its constructor

Alternatives

  • Add a call to the parent __construct() method.

Object of type %s is not callable

Description

There was an attempt to call a function whose name was provided in a variable, but that value could not be related to a callable code.

  • null : not a callable
  • true, false : booleans are not callable
  • int : integers are not callable
  • real : real are not callable
  • array : arrays are callable when they have two elements, with keys 0 and 1. First one is a class or an object of that class, the second is a string with a visible method name on that class. Otherwise, they are not valid callables.
  • string : strings are callable when they represent a function, with the leading backslash, \strlen, or a method, with a class name, a double colon ::, and a visible method name. Otherwise, they are not valid callables.
  • object : object are callable when their class has a __invoke method. This might be through a parent, like Closure. Otherwise, objects are not callable, although their method are.

All of these may be checked with a call to is_callable() on the variable, before using it.

Example

<?php

$method = new stdClass;
$method();

?>

Literal Examples

  • Object of type stdClass is not callable
  • Object of type X is not callable

Alternatives

  • Check the variable with is_callable(), before using it with the call syntax.
  • Use one of the available format.

In previous PHP versions, this error message used to be :ref:function-name-must-be-a-string.

object values within argument #1 $data to http_build_query() being interpreted as arrays is deprecated,

Description

http_build_query() walks its $data argument recursively, and treats any object value it finds along the way — not just the top-level argument — as if it were an array, iterating its public properties to build nested query keys such as public[public]=input. PHP 8.6 deprecates this implicit array-like treatment of nested object values, on top of the separate deprecation for passing an object as the top-level $data argument itself.

Example

<?php

class KeyVal {
    public $public = 'input';
}

$o = new KeyVal();
$nested = new KeyVal();
$o->public = $nested;

echo http_build_query($o);

?>

Literal Examples

  • http_build_query(): object values within argument #1 $data to http_build_query() being interpreted as arrays is deprecated, instead the $data argument should be preprocessed with get_object_vars()

Alternatives

  • Convert nested objects to arrays with get_object_vars() before assigning them, so the structure passed to http_build_query() is plain arrays all the way down.
  • Restructure the data so query parameters are built from arrays rather than objects.

In previous PHP versions, this error message used to be :ref:passing-an-object-for-argument-#1-$data-to-http_build_query()-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Octal escape sequence overflow %s is greater than \377

Description

Octal escape is a notation for double quoted strings, where a backslash followed by 3 digits is replaced by the character with this ASCII number. These ASCII numbers have a limit of 0o377.

Between 0o377 and 0o777, numbers are valid octals, and not ASCII numbers, so the error message appears.

Beyond 0o777, the sequence is not a valid octal anymore, and PHP does not process it, nor emit an error message.

Example

<?php

$a = "\500";

?>

Alternatives

  • Check the value in the octal sequence to be valid.
  • Add backslashes, to make the characters literals.

Offset not contained in string.

Description

strpos() searches for a string called $needle in another string called $haystack, starting at the offset passed as third argument, and called $offset.

The offset must be smaller than the full length of the $haystack: otherwise, PHP starts to search beyond the end of the data, and that will always fail.

This error message is shared by several PHP native and extension functions, namely mbstring and iconv: strpos(), strrpos(), stripos(), strripos(), mb_strpos(), mb_strrpos(), mb_stripos(), mb_strripos(), iconv_strpos and iconv_strrpos.

Before PHP 8.0, the failure was reported as a non-blocking warning. Since PHP 8.0, it is a fatal error.

Example

<?php

var_dump(strpos('abc', 'a', 4));

?>

Alternatives

  • Check that the offset is not beyond the length of the string.
  • Use a try catch around this methodcall.
  • Lengthen the source string.

In more recent PHP versions, this error message is now :ref:must-be-contained-in-argument-#1-($haystack).

Only arrays and Traversables can be unpacked

Description

The triple dot ... operator works on arrays and traversables, such as generator, iterators… It cannot work on other data structures.

Also, ... has a lower priority than the null-coalesce operator ??, so it applies to both branch of the operator.

Example

<?php

$a = null;
foo(...$a);

foo(...$a ?? range(1,2));
// displays 1, 2

function foo() {
    print_r(func_get_args());
}

?>

Alternatives

  • Check that the value is an array or a traverable before using the ... operator.
  • Use the ?? operator to give a value to null before the ... operator.
  • Use the ?: operator to give a value to empty data before the ... operator.

Only arrays can be unpacked in constant expression

Description

... may be used on both arrays and Traversable objects, but within a static constant expression, this operator only works on arrays, and cannot be used on objects, Traversable or not.

Example

<?php

const A = 2;

function foo($a = [...A]) {
    print_r($a);
}

foo();

?>

Alternatives

  • Rewrite the expression without the ... operator.
  • Convert the object into an array.

Only basic entities substitution is supported for multi-byte encodings other than UTF-8; functionality is equivalent to htmlspecialchars

Description

When passing a valid encoding to htmlentities(), but that is not supported, a warning is displayed, and an empty string is returned. This contrasts with the behavior when the encoding is not recognized, where PHP defaults to UTF-8, and returns something non empty.

Example

<?php

    var_dump( htmlentities("Café & 'quotes' and € euro", ENT_QUOTES, 'Big5') );
    // '', empty string

?>

Alternatives

  • Check that the used encoding is supported.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Only hooked properties may be declared abstract

Description

Hooked properties may be declared abstract, as long as the class is also abstract, and that one of the hook, get or set or both, have no body block.

In previous version, PHP would never allow properties to be abstract.

Example

<?php

    abstract class X {
        public abstract string $x;
    }

?>

Alternatives

  • Add an identity hook to the class, such as get => $this->x or set => $this->x = $value;.
  • Remove the abstract keyword.

In previous PHP versions, this error message used to be :ref:cannot-use-the-abstract-modifier-on-a-property.

Only internal classes can be registered as compiler attribute

Description

This error could not be reproduced so far. Help us by sending us any generating code.

Example


Alternatives

Only the first byte will be assigned to the string offset

Description

The array notation is available with strings, to both write and read. When writing to a string, the new assigned character must be a single character, and even, a single byte. This means that it is not possible to replace multiple characters, or to inject a longer string inside another one with such syntax.

As a side effect, this also applies to multi-byte characters: since they are represented on two, or more, characters, they cannot be injected in such syntax.

Example

<?php

$string = 'abc';
$string[3] = 'd'; 
// abcd
$string[4] = 'ef';
// warning
// abcde
$string[5] = '我'; // multi-byte character
// warning
// abcde� // <- invisible character at the end of the string


?>

Alternatives

  • Use preg_replace() or str_replace() to inject more than one character.
  • Splice the string and insert the new string in-between: substr($string, 0, $x).$newString.substr($string,$x+1).

Only the last parameter can be variadic

Description

A variadic parameter, marked with ..., collects every remaining argument passed to the function into an array. Since it consumes all the arguments left, no parameter can follow it: it must be the last one in the parameter list.

This is checked at compile time, as soon as a parameter is declared after a variadic one.

Example

<?php

function foo(...$a, $b) {}

?>

Alternatives

  • Move the variadic parameter to the end of the parameter list.
  • Use named arguments instead, if the extra parameter needs to keep a fixed conceptual position.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Only variable references should be returned by reference

Description

When a function returns a reference, it must return a variable, a property or an array’s item. It cannot return a literal value, a constant or an expression.

Example

<?php

function &foo() {
    return 1;
    
    return B;
}

?>

Alternatives

  • Put the literal in a variable, and return the variable.
  • Remove the reference in the method signature.

Only variable references should be yielded by reference

Description

With the & option in the signature, a generator is yielding values by reference, and not by value. This way, literal values cannot be yielded: they must be stored in a variable or property first.

Example

<?php

function &gen() {
    yield foo;
}

$gen = gen();
var_dump($gen->current());

?>

Alternatives

  • Store the literal in a variable and yield the variable.
  • Remove the & in the method signature.

Only variables can be passed by reference

Description

Methods arguments may be passed by value or by reference. The first one is the default behavior, and the second one is optional: it is identified with the &, before the name of the argument.

When an argument is passed by reference, the calling context passes a variable, and conserves a handle to the modified variable after the execution of the method. The handle points to a data container, such as a variable, a property, a static property or a array item.

When passing literal values or constants, global or class, a distinct error is emitted, as there cannot be a reference to them. They can only be passed by value.

This error message is emitted when a value is returned, and feed into a reference argument.

Example

<?php

function foo(&$a) {}

foo(1);

?>

Alternatives

  • Store the value in a variable, and pass the variable to the method.
  • Remove the reference from the called method signature.

In more recent PHP versions, this error message is now :ref:only-variables-should-be-passed-by-reference.

Only variables should be passed by reference

Description

Methods arguments may be passed by value or by reference. The first one is the default behavior, and the second one is optional: it is identified with the &, before the name of the argument.

When an argument is passed by reference, the calling context passes a variable, and conserves a handle to the modified variable after the execution of the method. The handle points to a data container, such as a variable, a property, a static property or a array item.

When passing literal values or constants, global or class, a distinct error is emitted, as there cannot be a reference to them. They can only be passed by value.

This error message is emitted when a value is returned, and feed into a reference argument.

Example

<?php

function foo(int &$int) {
    // doSomething
}

// the result of a function is still a literal value
foo(abs(-3));
// a direct literal value generates that error
foo(3);

// This one is a notice
enum E {
    case A;
    case B;
    case C;
}
usort(E::cases());
//The sort won't be visible, as the array is not accessible and must be called again, unsorted.

?>

Alternatives

  • Store the value in a variable, and pass the variable to the method.
  • Remove the reference from the called method signature.

In previous PHP versions, this error message used to be :ref:only-variables-can-be-passed-by-reference.

open_basedir prohibits opening %s

Description

open_basedir is a PHP directive which limits access of the inclusion functions, such as include and require, to include files which are outside the path specified with open_basedir.

Example

<?php

include '/private/folder/secret.php';

?>

Alternatives

  • Update the open_basedir directive to allow access to the file.
  • Update the inclusion path to target a file that falls within the paths in the open_basedir directive.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s)

Description

This is an alt error message raised when a PHP extension tries to access a file, while the open_basedir is enabled. This may happen with XML extensions, sqlite3, file, tidy, mysqli, readline, stream, curl, etc. This list is not exhaustive.

Example

<?php

    $db = new SQLite3('/forbidden/path/to/sqlite3.db');

?>

Literal Examples

  • open_basedir restriction in effect. File(example.php) is not within the allowed path(s): (.::/tmp/)

Alternatives

  • Make sure the file path lies within the open_basedir directive’s path.
  • Change the value of the open_basedir directive.
  • Check the value of the open_basedir directive for typos.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Optional parameter %s declared before required parameter %s is implicitly treated as a required parameter

Description

An optional parameter has a default value, while a required parameter doesn’t. In a method signature, PHP recommends to set the required parameters first, then the optional parameter.

When this is not the case, PHP is unable to understand if an argument has to be assigned to a parameter, or if it can be skipped, and assigned to the next required. When this happens, any required parameter makes previously defined parameter also required.

Example

<?php
	
function foo($a = 1, $b) {}
	
?>

Literal Examples

  • Optional parameter $a declared before required parameter $b is implicitly treated as a required parameter

Alternatives

  • Remove the default value of the early optional parameter.
  • Add a default value of the late required parameter.

In previous PHP versions, this error message used to be :ref:required-parameter-$%s-follows-optional-parameter-$%s. In more recent PHP versions, this error message is now :ref:%s():-optional-parameter-$%s-declared-before-required-parameter-$%s.

Parameter $%s of %s hook %s::$%s must not be pass-by-reference

Description

The parameter of a set property hook receives the value being assigned to the property. It cannot be declared as pass-by-reference with a leading &, since a property hook is not meant to modify the caller’s variable; it only reacts to, or transforms, the value on its way into the property.

Example

<?php

class X
{
    public string $property {
        set(&$value) {
            $this->property = $value;
        }
    }
}

?>

Literal Examples

  • Parameter $value of set hook X::$property must not be pass-by-reference

Alternatives

  • Remove the & from the hook’s parameter.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Parameter $%s of %s hook %s::$%s must not be variadic

Description

A set property hook must accept exactly one, ordinary parameter: the incoming value. Declaring it as variadic with ... does not make sense, since the hook is always called with exactly one value, never with a variable number of arguments.

Example

<?php

class X
{
    public string $property {
        set(string ...$value) {
            $this->property = implode(',', $value);
        }
    }
}

?>

Literal Examples

  • Parameter $value of set hook X::$property must not be variadic

Alternatives

  • Remove the ... from the hook’s parameter, and declare it as a regular parameter.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Parameter $%s of %s hook %s::$%s must not have a default value

Description

The parameter of a set property hook cannot declare a default value. The hook is always invoked with the value being assigned to the property, so a default value would never actually be used, and PHP rejects it as meaningless.

Example

<?php

class X
{
    public string $property {
        set(string $value = 'default') {
            $this->property = $value;
        }
    }
}

?>

Literal Examples

  • Parameter $value of set hook X::$property must not have a default value

Alternatives

  • Remove the default value from the hook’s parameter.
  • If a fallback value is needed, assign a default to the property itself, or handle it inside the hook’s body.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Parameter %d must be passed by reference

Description

When a parameter is set to be passed by reference, there is a & character before its name. In that case, the argument must be a data container, such as a variable, a property, a static property, an array index, but it cannot be a literal value, a constant, or the result of an expression.

Example

<?php

function foo(&$a) {}

// invalid cases
foo(1);
foo(1 + 2);

const A = 1;
foo(A);

class X {
    const B = 2;
}
foo(X::B);

?>

Literal Examples

  • foo(): Argument #1 ($a) must be passed by reference, value given

Alternatives

  • Store the value in a variable and passe the variable.
  • Remove the reference in the method signature.

In more recent PHP versions, this error message is now :ref:%s%s%s():-argument-#%d%s%s%s-must-be-passed-by-reference,-value-given.

Parameter must be an array or an object that implements Countable

Description

The count() native function only count elements that are arrays, or objects that implements the Countable interface. Anything else yields a fatal error.

Example

<?php

$value = null;
echo count($value);

?>

Alternatives

  • Check for type before using count: is_array or instanceof \Countable.

In more recent PHP versions, this error message is now :ref:must-be-of-type-countable|array,-%s-given.

Parameter must have a name

Description

This is an internal error, when the engine detect that a parameter was set on a function without a name. This should not compile anyway.

Example


Alternatives

  • Change of PHP version.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Parameter uses ‘parent’ as type hint although class does not have a parent!

Description

This error is a Reflection API error. It appears when the code tries to get information about the type of a parameter, that was defined as ‘parent’ while it is not a valid code.

Example

<?php

class X {
	function foo(parent $a) {}
}

?>

Alternatives

  • Check the name of the type before trying to instantiate it.

In more recent PHP versions, this error message is now :ref:cannot-use-"parent"-when-current-class-scope-has-no-parent.

Partial application of %s() expects %s %d arguments, %d given

Description

PHP 8.6 introduces partial function application: a ? in an argument position stands in for a value to be supplied later, and turns the call into a Closure bound to whichever arguments were already given. The placeholder ... on its own captures all of a function’s still-missing required parameters instead, but a single ? does not, so the call must still provide at least one argument slot (a value or a ?) for every required parameter.

Here, add() requires 3 arguments, but the partial application supplies only 2 slots (the value 1 and one ?), so PHP rejects it as underspecified rather than silently creating a closure that would itself fail as soon as it were called.

Example

<?php

function add($a, $b, $c) {
    return $a + $b + $c;
}

$partial = add(1, ?);

?>

Literal Examples

  • Partial application of add() expects exactly 3 arguments, 2 given

Alternatives

  • Provide one argument slot (a value or a ? placeholder) for every required parameter, or replace the trailing ? with … to defer all remaining required parameters at once: add(1, …).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Partial application of %s() expects at most %d arguments, %d given

Description

PHP 8.6 introduces partial function application: a ? in an argument position stands in for a value to be supplied later, and turns the call into a Closure bound to whichever arguments were already given. A partial-application call still can’t supply more argument slots (values or ? placeholders combined) than the target function actually declares, unless that function is itself variadic.

Here, add() declares only 2 parameters, but the partial application supplies 4 slots (1, 2, 3, and a trailing ?), so PHP rejects it instead of creating a closure that could never be called successfully.

Example

<?php

function add($a, $b) {
    return $a + $b;
}

$partial = add(1, 2, 3, ?);

?>

Literal Examples

  • Partial application of add() expects at most 2 arguments, 4 given

Alternatives

  • Don’t supply more argument slots (values or ? placeholders) to a partial application than the function declares, unless the function itself accepts a variadic parameter.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

passing a negative integer to argument #3 ($width) is deprecated

Description

mb_strimwidth() trims a string to a given display width. Its $width argument used to accept negative values, in which case the width was measured from the end of the string instead of from $start.

A review of public code found essentially no real-world usage of a negative $width, and the feature made the function’s behavior harder to reason about for little benefit. As of PHP 8.3.0, passing a negative integer for this argument is deprecated.

Example

<?php

echo mb_strimwidth('Hello world', 0, -5, '...');

?>

Alternatives

  • Compute the trimmed width explicitly (e.g. using mb_strwidth()) and pass a positive value to mb_strimwidth().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_strimwidth

Passing a secret of a type other than string is deprecated because it implicitly converts to a string, potentially hiding bugs

Description

The xxh3 and xxh128 hashing algorithms accept an optional 'secret' entry in the options array passed to hash()/hash_init(), used instead of a plain integer seed to initialize the hash. It is documented as a string, but PHP did not previously enforce that: any other type was silently converted with an implicit (string) cast, so a programmer who passed, say, an int would get a working-looking hash computed from an unintended value, with no indication anything was wrong.

As of PHP 8.4, passing a non-string ‘secret’ emits this deprecation notice before the implicit conversion happens, so the mistake is no longer silent. A future version is expected to throw a ValueError instead.

Example

<?php

try {
    // 'secret' is documented as a string; passing an int silently
    // converts it with (string) instead of being used as given.
    hash('xxh3', 'some data', false, ['secret' => 12345]);
} catch (\Throwable $e) {
    // xxh3 also requires the secret to be at least 136 bytes long once
    // converted to a string -- unrelated to the type deprecation itself.
}

?>

Literal Examples

  • hash(): Passing a secret of a type other than string is deprecated because it implicitly converts to a string, potentially hiding bugs

Alternatives

  • Pass a string directly for ‘secret’, e.g. a value produced by random_bytes().
  • If the value naturally isn’t a string, convert it explicitly and document why, e.g. [‘secret’ => (string) $value].
  • Use the ‘seed’ option (an int) instead of ‘secret’ when a full custom secret is not actually needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing a seed of a type other than int is deprecated because it is ignored

Description

The xxh3 and xxh128 algorithms accept an optional 'seed' entry (an int) in the options array passed to hash()/hash_init(). Unlike the older murmur3*/xxh32/xxh64 algorithms – where a non-int seed is coerced and effectively becomes 0 – these two algorithms take a different code path: when 'seed' is not an int, it is simply ignored altogether, and neither the seed nor a secret is applied. Code that believes it configured a seed silently gets the plain, unseeded hash instead.

As of PHP 8.4, passing a non-int ‘seed’ to xxh3/xxh128 emits this deprecation notice so the silent no-op is no longer invisible. A future version is expected to throw a ValueError instead.

Example

<?php

// 'seed' is documented as an int; xxh3 simply ignores it when it
// isn't one, silently falling back to the unseeded, default hash.
var_dump(hash('xxh3', 'some data', false, ['seed' => '1234']));

?>

Literal Examples

  • hash(): Passing a seed of a type other than int is deprecated because it is ignored

Alternatives

  • Pass an actual int for ‘seed’, e.g. [‘seed’ => 1234] rather than a numeric string.
  • Cast the value explicitly if it is computed dynamically: [‘seed’ => (int) $value].
  • Use ‘secret’ (a string) instead of ‘seed’ when more entropy than a single int provides is needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing a seed of a type other than int is deprecated because it is the same as setting the seed to 0

Description

The murmur3a, murmur3c, murmur3f, xxh32 and xxh64 algorithms accept an optional 'seed' entry (an int) in the options array passed to hash()/hash_init(), defaulting to 0 when not given. When a non-int value is passed, these algorithms’ code checks the type, finds it isn’t an int, and simply falls through without ever assigning it – leaving the seed at its already-initialized default of 0. The visible effect is identical to never having passed 'seed' at all, which is easy to miss since no error was raised.

As of PHP 8.4, passing a non-int ‘seed’ to one of these algorithms emits this deprecation notice. Note that xxh3/xxh128 take a related but distinct code path for the same mistake, documented separately since their non-int seed is ignored rather than treated as 0 (the two happen to behave the same when the intended seed actually was 0, but not otherwise).

Example

<?php

// 'seed' is documented as an int; murmur3a treats anything else as
// though 'seed' had simply been left at its default, 0.
var_dump(hash('murmur3a', 'some data', false, ['seed' => '1234']));
var_dump(hash('murmur3a', 'some data', false, ['seed' => 0]));
// the two lines above produce the exact same hash

?>

Literal Examples

  • hash(): Passing a seed of a type other than int is deprecated because it is the same as setting the seed to 0

Alternatives

  • Pass an actual int for ‘seed’, e.g. [‘seed’ => 1234] rather than a numeric string.
  • Cast the value explicitly if it is computed dynamically: [‘seed’ => (int) $value].
  • If a seed of 0 was genuinely intended, pass [‘seed’ => 0] explicitly instead of relying on a mistyped value falling back to it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for argument #%“ PRIu32 “ $vars to mb_convert_variables() is deprecated, call get_object_vars() first instead

Description

mb_convert_variables() converts the character encoding of every value passed to it — strings, arrays, or objects — in place, recursing into arrays and objects alike. Each variadic argument after the first two occupies a different, dynamic position ($vars), so the deprecation names whichever argument number the object was actually found at, not a fixed one. PHP 8.6 deprecates passing an object anywhere in that variadic list, whether directly or nested inside an array.

Example

<?php

class Nested {
    public $inner;
}

$nested = new Nested();
$nested->inner = 'some text';

mb_convert_variables('UTF-8', 'auto', $nested);

?>

Literal Examples

  • mb_convert_variables(): Passing an object for argument #3 $vars to mb_convert_variables() is deprecated, call get_object_vars() first instead
  • mb_convert_variables(): Passing an object for argument #7 $vars to mb_convert_variables() is deprecated, call get_object_vars() first instead

Alternatives

  • Convert the object to an array first with get_object_vars() and pass that instead.
  • Convert only the scalar string properties you need, individually.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for argument #1 $array to array_walk() is deprecated, call get_object_vars() first instead

Description

array_walk() has always accepted an object in place of $array as an undocumented convenience, iterating over its accessible properties the same way it iterates array elements — including private and protected properties when called from inside the class. PHP 8.6 deprecates this implicit array/object interchangeability, since it makes visibility rules leak into what looks like ordinary array iteration.

Example

<?php

class Test {
    public $foo = 'foo';
    public $bar = 'bar';
}

array_walk(new Test(), function ($value, $key) {
    var_dump($key, $value);
});

?>

Alternatives

  • Convert the object to an array first with get_object_vars($obj) (from outside the class) and pass that to array_walk().
  • Iterate the object directly with foreach if you don’t need array_walk()’s by-reference callback semantics.

In more recent PHP versions, this error message is now :ref:passing-an-object-for-argument-#1-$array-to-array_walk_recursive()-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for argument #1 $array to array_walk_recursive() is deprecated, call get_object_vars() first instead

Description

Like array_walk(), array_walk_recursive() has always accepted an object in place of $array, iterating over its accessible properties (recursing into any that are themselves arrays or objects) instead of requiring an array. PHP 8.6 deprecates this implicit object handling, along with the equivalent case in array_walk().

Example

<?php

class Test {
    public $foo = 'foo';
    public $bar = ['x', 'y'];
}

array_walk_recursive(new Test(), function ($value, $key) {
    var_dump($key, $value);
});

?>

Alternatives

  • Convert the object to an array first with get_object_vars($obj) and pass that to array_walk_recursive().
  • Write a small recursive helper for objects if visibility of nested properties matters.

In previous PHP versions, this error message used to be :ref:passing-an-object-for-argument-#1-$array-to-array_walk()-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for argument #1 $data to http_build_query() is deprecated, call get_object_vars() first instead

Description

http_build_query()’s $data parameter is documented as taking an array, but has always also accepted an object, building the query string from its accessible (public, from outside the class) properties. PHP 8.6 deprecates passing an object directly as $data. Passing an object nested inside the array is separately deprecated too.

Example

<?php

class KeyVal {
    public $public = 'input';
    protected $protected = 'hello';
    private $private = 'world';
}

echo http_build_query(new KeyVal());

?>

Alternatives

  • Convert the object to an array first with get_object_vars($obj) and pass that to http_build_query().
  • If the object implements a mapping interface, expose its data as an array explicitly, e.g. via a dedicated method.

In more recent PHP versions, this error message is now :ref:object-values-within-argument-#1-$data-to-http_build_query()-being-interpreted-as-arrays-is-deprecated,.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for argument #2 $option to deflate_init() is deprecated, call get_object_vars() first instead

Description

deflate_init()’s $options argument is documented as taking an associative array (level, memory, window, strategy, dictionary), but has always also accepted an object, reading the same keys off its public properties. PHP 8.6 deprecates passing an object here, matching the equivalent deprecation for inflate_init().

Example

<?php

class Options {
    public int $level = 3;
}

$context = deflate_init(ZLIB_ENCODING_RAW, new Options());

?>

Alternatives

  • Convert the object to an array first with get_object_vars($obj) and pass that as $options.
  • Pass an associative array literal instead of building an options object.

In more recent PHP versions, this error message is now :ref:passing-an-object-for-argument-#2-$option-to-inflate_init()-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for argument #2 $option to inflate_init() is deprecated, call get_object_vars() first instead

Description

inflate_init()’s $options argument is documented as taking an associative array (level, memory, window, dictionary), but has always also accepted an object, reading the same keys off its public properties. PHP 8.6 deprecates passing an object here, matching the equivalent deprecation for deflate_init().

Example

<?php

class Options {
    public int $window = 15;
}

$context = inflate_init(ZLIB_ENCODING_RAW, new Options());

?>

Alternatives

  • Convert the object to an array first with get_object_vars($obj) and pass that as $options.
  • Pass an associative array literal instead of building an options object.

In previous PHP versions, this error message used to be :ref:passing-an-object-for-argument-#2-$option-to-deflate_init()-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for filter parameters for %s is deprecated, call get_object_vars() first instead

Description

stream_filter_append() (and stream_filter_prepend()) pass their $params argument through to the named stream filter. The bundled zlib.deflate and zlib.inflate filters accept it as an associative array of options, but have always also accepted an object, reading the same keys off its public properties. PHP 8.6 deprecates passing an object for these two filters — the %s in the message is replaced with the filter name, zlib.deflate or zlib.inflate. The bzip2 filters have the same deprecation under distinct, filter-specific messages.

Example

<?php

class Options {
    public int $level = 9;
}

$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, new Options());
fwrite($fp, 'Hello world');

?>

Literal Examples

  • stream_filter_append(): Passing an object for filter parameters for zlib.deflate is deprecated, call get_object_vars() first instead
  • stream_filter_append(): Passing an object for filter parameters for zlib.inflate is deprecated, call get_object_vars() first instead

Alternatives

  • Convert the object to an array first with get_object_vars($obj) and pass that as the filter parameters.
  • Pass an associative array literal instead of building an options object.

In more recent PHP versions, this error message is now :ref:passing-an-object-for-filter-parameters-for-bzip2.compress-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for filter parameters for bzip2.compress is deprecated, call get_object_vars() first instead

Description

The bzip2.compress stream filter accepts its parameters as an associative array (blocksize100k, workfactor), but has always also accepted an object, reading the same keys off its public properties. PHP 8.6 deprecates passing an object here, matching the equivalent deprecation for bzip2.decompress and for the zlib filters.

Example

<?php

class ParamsCompress {
    public int $blocks = 5;
    public int $work = 10;
}

$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, new ParamsCompress());
fwrite($fp, 'Hello world');

?>

Alternatives

  • Convert the object to an array first with get_object_vars($obj) and pass that as the filter parameters.
  • Pass an associative array literal instead of building an options object.

In previous PHP versions, this error message used to be :ref:passing-an-object-for-filter-parameters-for-%s-is-deprecated,-call-get_object_vars()-first-instead. In more recent PHP versions, this error message is now :ref:passing-an-object-for-filter-parameters-for-bzip2.decompress-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing an object for filter parameters for bzip2.decompress is deprecated, call get_object_vars() first instead

Description

The bzip2.decompress stream filter accepts its parameters as an associative array (small, concatenated), but has always also accepted an object, or a plain boolean, reading the array-equivalent keys off an object’s public properties. PHP 8.6 deprecates passing an object here, matching the equivalent deprecation for bzip2.compress and for the zlib filters.

Example

<?php

class ParamsDecompress {
    public bool $concatenated = true;
    public bool $small = true;
}

$fp = fopen('php://output', 'w');
stream_filter_append($fp, 'bzip2.decompress', STREAM_FILTER_WRITE, new ParamsDecompress());

?>

Alternatives

  • Convert the object to an array first with get_object_vars($obj) and pass that as the filter parameters.
  • Pass an associative array literal instead of building an options object.

In previous PHP versions, this error message used to be :ref:passing-an-object-for-filter-parameters-for-bzip2.compress-is-deprecated,-call-get_object_vars()-first-instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing bool is deprecated, use 1 or -1 instead

Description

IntlCalendar::roll() (and the procedural intlcal_roll()) add an amount to a calendar field, wrapping around instead of carrying into the next field – e.g. rolling the hour field past 23 wraps back to 0 rather than advancing the day. The $value argument is meant to be a signed int amount, but PHP has always also special-cased a bool: true is interpreted as 1 and false as -1 – not the 0 that PHP’s normal bool-to-int coercion would produce, which is itself a common source of confusion, and does not appear to serve any purpose the plain integers 1/-1 don’t already cover.

As of PHP 8.1, passing a bool for this argument emits this deprecation notice; it still works exactly as before for now, but relying on this special-cased, non-standard coercion is expected to stop being supported in a future version.

Example

<?php

$cal = IntlCalendar::createInstance('UTC');

// true/false used to mean 'roll up'/'roll down', mirroring the
// underlying ICU API, which actually expects a signed amount.
$cal->roll(IntlCalendar::FIELD_HOUR_OF_DAY, true);

?>

Literal Examples

  • IntlCalendar::roll(): Passing bool is deprecated, use 1 or -1 instead

Alternatives

  • Pass 1 instead of true to roll the field up by one.
  • Pass -1 instead of false to roll the field down by one.
  • Pass any other signed int to roll by more than one step in either direction.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing connection object as an argument is deprecated

Description

mysqli_get_client_info() reports the version of the underlying MySQL client library that PHP was compiled/linked against. This information is a property of the client library itself, not of any particular connection, so the function never actually needed a connection argument, even though its procedural signature historically accepted one for consistency with other mysqli_* functions.

Passing a connection object to this function has no effect on the result, and is deprecated as of PHP 8.1.0 to make that clear.

Example

<?php

$mysqli = mysqli_connect('localhost', 'user', 'password');

// The connection argument is ignored by this function.
echo mysqli_get_client_info($mysqli);

?>

Alternatives

  • Call mysqli_get_client_info() without arguments, e.g. mysqli_get_client_info().
  • When using the object-oriented API, use mysqli_get_client_info() (not a method call), since the client info is not connection-specific.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mysqli_get_client_info

Passing E_USER_ERROR to trigger_error() is deprecated since 8.4, throw an exception or call exit with a string message instead

Description

The error level E_USER_ERROR is deprecated since PHP 8.4. It should be replaced with a thrown exceptions. The other levels, E_USER_NOTICE and E_USER_WARNING are still available.

Example

<?php

trigger_error('message', E_USER_ERROR);

?>

Alternatives

  • Throw an execption.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See E_USER_ERROR

Passing false or null is deprecated since 8.4

Description

Passsing false or null to dba_key_split() is deprecated since PHP 8.4.

Example

<?php

var_dump(dba_key_split(null));
var_dump(dba_key_split(false));

?>

Alternatives

  • Use an empty string.

Passing non-callable strings is deprecated since 8.4

Description

xml_set_processing_instruction_handler() requires a valid method to be passed. Closure, first class callable, and other callable structures are possible. When using a string, make sure it references an existing function name.

Example

<?php

// empty string is not a valid callable
xml_set_processing_instruction_handler($parser, '');

// This cannot be a valid function name
xml_set_processing_instruction_handler($parser, '123foo');

?>

Alternatives

  • Use a valid function name: non empty string, and a valid name format.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing null is deprecated, instead the last opened directory stream should be provided

Description

When calling dir() twice, it was possible to use null the second time to open the same directory. Since PHP 8.1, it is not possible anymore, and the actual name of the directory must be provided.

Example

<?php

dir('/tmp'); // opens /tmp

dir(null); // opens /tmp

?>

Alternatives

  • Always use the name of the directory when calling dir().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Passing the $mode parameter is deprecated since 8.4, as it has been ignored since 8.1

Description

mysqli_store_result() (and mysqli::store_result()) used to accept an optional $mode flag, MYSQLI_STORE_RESULT_COPY_DATA, telling mysqlnd to copy fetched data out of its internal buffer instead of referencing it directly. As of PHP 8.1, mysqlnd’s internal buffering changed and this flag no longer has any effect: the parameter is silently ignored no matter what is passed.

Since code could keep passing $mode for years without any indication that it did nothing, PHP 8.4 adds a deprecation notice specifically for that: passing the parameter at all, regardless of its value, is now reported as deprecated.

Example

<?php

$mysqli = new mysqli('localhost', 'user', 'password', 'database');
$mysqli->query('SELECT id FROM users', MYSQLI_USE_RESULT);

$result = $mysqli->store_result(MYSQLI_STORE_RESULT_COPY_DATA);

?>

Literal Examples

  • Passing the $mode parameter is deprecated since 8.4, as it has been ignored since 8.1

Alternatives

  • Stop passing the $mode argument (and the MYSQLI_STORE_RESULT_COPY_DATA constant) to store_result(); it has had no effect since PHP 8.1.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [The $mode parameter (MYSQLI_STORE_RESULT_COPY_DATA) already stopped having any effect in PHP 8.1, without any notice. PHP 8.4 only adds the deprecation notice; the (lack of) behavior itself is unchanged.](The $mode parameter (MYSQLI_STORE_RESULT_COPY_DATA) already stopped having any effect in PHP 8.1, without any notice. PHP 8.4 only adds the deprecation notice; the (lack of) behavior itself is unchanged.)

Passing the encoding as third parameter is deprecated. Use an explicit zero offset

Description

PHP used to recognize automatically the third parameter when it was actually the encoding, and noth the offset of start. The latter is an integer, while the former is a string.

In PHP 8.0, it is now a normal type error.

Example

<?php

// Valid in PHP 7.x
echo mb_strrpos('abc', 'a', 'utf8');

// Valid in PHP 8.+
echo mb_strrpos('abc', 'a', 0, 'utf8');
echo mb_strrpos('abc', 'a', encoding: 'utf8');

?>

Alternatives

  • Use named parameters.
  • Add a 0 as third parameter (the default value for offset).

In more recent PHP versions, this error message is now :ref:argument-#%d-($%s)-must-be-of-type-%s,-%s-given.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See mb_strrpos

Path cannot be empty

Description

fopen()’s first argument is of type string, though the empty string is not allowed, as it does not lead to any file.

Example

<?php

fopen('', 'r');

?>

Literal Examples

  • fopen(): Path cannot be empty

Alternatives

  • Check the name of the file with empty() before using it with fopen().
  • Check the name of the file against ‘’ (empty string) before using it with fopen().

In previous PHP versions, this error message used to be :ref:filename-cannot-be-empty. In more recent PHP versions, this error message is now :ref:path-must-not-be-empty.

Path must not be empty

Description

fopen()’s first argument is of type string, though the empty string is not allowed, as it does not lead to any file.

Example

<?php

fopen('', 'r');

?>

Literal Examples

  • fopen(): Path cannot be empty

Alternatives

  • Check the name of the file with empty() before using it with fopen().
  • Check the name of the file against ‘’ (empty string) before using it with fopen().

In previous PHP versions, this error message used to be :ref:path-cannot-be-empty.

Power of base 0 and negative exponent is deprecated

Description

Requesting a negative exponent on 0 yields this error message. While PHP 8.3- used to generate INF as result, PHP 8.4 is moving toward generating a DivisionByZeroError: this will be set in PHP 9.0.

Example

<?php

$x = 0;

$y = $x ** -2;

?>

Alternatives

  • Check for 0 before raising a negative power. Positive powers are OK.
  • Check for negative power before raising a power of 0.
  • Use the PHP 8.4 function fpow() that has the future behavior, with a try/catch structure.

Private constant %s::%s cannot be final as it is not visible to other classes

Description

A private constant is restricted to being used by its definition class only: as such, it is not visible to other classes, including children. A final class constant cannot be overwritten by a child class.

private and final a both mutually exclusive.

Example

<?php

class X {
    private final const A = 1;
}

?>

Literal Examples

  • Private constant C::A cannot be final as it is not visible to other classes

Alternatives

  • Relax the private keyword with protected, or public.
  • Remove the final keyword.

Private methods cannot be final as they are never overridden by other classes

Description

Final methods are only available in the class where they are defined. If such a method is defined in one of the child class, it is considered a distinct method. As such, the final keyword doesn’t apply, and even is misleading.

Example

<?php

class X {
	private final function foo() {}
}

?>

Alternatives

  • Remove the final keyword in the method definition.
  • Change the visibility to protected to public.

Producing output from user output handler %s is deprecated

Description

A user output handler registered with ob_start() is expected to receive the current buffer contents and return the (possibly transformed) string to send further down the output stack. Historically, nothing prevented such a handler from also producing its own output directly (for instance with echo or print), in addition to returning a value.

Output produced this way bypasses the normal buffering contract and is silently discarded, which usually indicates a bug in the handler rather than an intentional behavior. As of PHP 8.5.0, doing so raises a deprecation notice naming the offending handler.

Example

<?php

ob_start(function (string $buffer): string {
    // Directly emitting output from the handler, instead of
    // only returning the transformed buffer.
    echo 'debug: ', strlen($buffer), " bytes\n";

    return $buffer;
});

echo 'Hello world';
ob_end_flush();

?>

Alternatives

  • Only communicate the processed content through the handler’s return value; do not echo/print from within it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ob_start

Property %s does not exist

Description

This error happens when the Reflection API fails at getting the description of a non-existent property. The name of the property should be checked before using the getProperty method.

Example

<?php
    $class = new ReflectionClass('ReflectionClass');
    $property = $class->getProperty('unkown');
    var_dump($property);
?>

Literal Examples

  • Property unknown does not exist

Alternatives

  • Check that the property exists before using getProperty.

In more recent PHP versions, this error message is now :ref:property-%s::$%s-does-not-exist.

Property %s::$%s cannot have type %s

Description

Some native PHP types are not allowed with a property. This is the case of void, never and callable. Any mention of them, alone or in a compsed type generates this error.

Example

<?php

class X {
	public callable|int $property = 1;
}

?>

Literal Examples

  • Property x::$p cannot have type callable

Alternatives

  • Remove any illegal type from the definition of the property.
  • Remove all types from the definition of the property.

Property %s::$%s does not exist

Description

This error happens when the Reflection API fails at getting the description of a non-existent property. The name of the property should be checked before using the getProperty method.

Example

<?php
    $class = new ReflectionClass('ReflectionClass');
    $property = $class->getProperty('unkown');
    var_dump($property);
?>

Literal Examples

  • Property ReflectionClass::$unknown does not exist

Alternatives

  • Check that the property exists before using getProperty.

In previous PHP versions, this error message used to be :ref:property-%s-does-not-exist.

Property cannot be both final and private

Description

When a property is final, it cannot be overridden in a child class; when a class is private, it is only available in the current class.

Hence, a property cannot be final and private at the same time.

In this situation, the property may not final, as there are no property hooks.

Example

<?php

class X {
	final private $p;
}

?>

Alternatives

  • Remove the hooks, and use the magic methods __get/__set.
  • Remove the final keyword.
  • Remove the private keyword and use protected or public.

In previous PHP versions, this error message used to be :ref:cannot-use-the-final-modifier-on-a-property.

Property hook cannot be both abstract and final

Description

This error is emitted when a property is defined in an interface, with the final option. There, a property hook is automatically abstract, as it is part of an interface, so the abstract option is understated.

In a class or a trait, the reported error is that abstract is not allowed on a property hook.

Example

<?php

interface I {
    public int $p {
        final get;
    }
}

?>

Alternatives

  • Remove the final option from the property hook.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Property hook cannot be both abstract and private

Description

Property hook may be private, as in only available to current class, or abstract, as in always redefined in a child class, but not both at the same time.

It is the same as for methods.

Example

<?php

class X {
    private abstract $property { get; }
}

?>

Alternatives

  • Make the method protected or public.
  • Remove the abstract keyword.

Property hook cannot be both final and private

Description

When a property is final, it cannot be overridden in a child class; when a class is private, it is only available in the current class.

Hence, a property cannot be final and private at the same time.

In this situation, the property may be final, due to the property hooks. A property without hooks cannot be final.

Example

<?php

class X {
	private $p {
		final get => 2;
		set => $this->p = $value;
	}
}

?>

Alternatives

  • Remove the hooks, and use the magic methods __get/__set.
  • Remove the final keyword.
  • Remove the private keyword and use protected or public.

Property hook list must not be empty

Description

It is possible to add a block, after a property definition. This is where the get and set methods are defined. There can be one or two of these methods, but the block just cannot be left empty.

Example

<?php

class X {
	public int $p = 3 {	}
}

?>

Alternatives

  • Create at least one accessor method in the block.
  • Remove the block.

Property in interface cannot be explicitly abstract.

Description

While PHP 8.4 supports properties in an interface, as long as they are defining hooks, it is not possible to use explicitly the option abstract.

Example

<?php

interface I {
    abstract $p { get; }
}

?>

Alternatives

  • Remove the option abstract. May be use public instead.
  • Move the property definition to an abstract class.

Property in interface cannot be final

Description

While PHP 8.4 supports properties in an interface, as long as they are defining hooks, it is not possible to use the final option: in fact, the property hook does not have a body, so there is no code to finalize.

Example

<?php

interface I {
    final $p { get; }
}

?>

Alternatives

  • Remove the final option.
  • Move the property definition to an abstract class.

Property in interface cannot be protected or private

Description

While PHP 8.4 supports properties in an interface, as long as they are defining hooks, it is not possible to use another visibility than public.

Example

<?php

interface I {
    private $p { get; }
}

?>

Alternatives

  • Make the property visible.
  • Move the property definition to an abstract class.

Property with asymmetric visibility %s::$%s must have type

Description

Asymmetric visibility, such as protected(set) only applies to a typed property.

Example

<?php

class X {
	static protected(set) int $property;
}

?>

Literal Examples

  • Property with asymmetric visibility x::$property must have type

Alternatives

  • Remove the asymmetric property.
  • Add a type to the property.

Property x::$p cannot have type void

Description

Void is a type, that can only be used with return type, on methods or functions. Here, void represents the absence of value: this is not possible for a property or an argument. The null value is then the closest possible type that can be assigned to a property, yet representing no value.

Example

<?php

class X {
    private void $property;
}

?>

Alternatives

  • Use another type for the property.
  • Remove the property.
  • Use the null type.

Providing a string that is not one byte long is deprecated. Use ord($str[0]) instead

Description

The ord() function returns the ordinal value of the first byte of a string. When the provided string is longer than one byte, only the first byte is used and the remaining bytes are silently discarded. This implicit behavior is a source of confusion, especially when working with multi-byte encodings such as UTF-8, where a single character may span several bytes. To make the intent explicit, use the $str[0] syntax to extract the first byte before passing it to ord().

Example

<?php

    $str = '我';
    
    echo ord($str); 

?>

Alternatives

  • Use the $str[0] rather than the whole string.
  • Use substr($str, 0, 1) on the string, as long as the string is not multi-byte.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ordNonSingleByteString

Providing a value not in-between 0 and 255 is deprecated, this is because a byte value must be in the [0, 255] interval. The value used will be constrained using %% 256

Description

chr() builds a one-character string from an integer code point, but a string byte can only hold a value between 0 and 255. Historically, chr() accepted any int and silently wrapped out-of-range values by computing value %% 256, so chr(256) quietly produced the same byte as chr(0). This is almost always the sign of an arithmetic mistake upstream (an off-by-one, a missing modulo, a value that was never validated).

As of PHP 8.5, calling chr() with a value outside the [0, 255] interval emits this deprecation notice. The returned byte is unchanged – PHP still applies %% 256 to constrain the value – so existing output is not affected, but code should stop relying on the implicit wrap.

Example

<?php

// A byte can only hold a value in [0, 255]; anything outside
// that range was silently wrapped with % 256.
echo chr(256);  // same as chr(0)
echo chr(-1);   // same as chr(255)

?>

Literal Examples

  • chr(): Providing a value not in-between 0 and 255 is deprecated, this is because a byte value must be in the [0, 255] interval. The value used will be constrained using %% 256

Alternatives

  • Apply the modulo explicitly before calling chr(), e.g. chr($value %% 256), so the intent is documented and the notice is silenced.
  • Validate the value is already within [0, 255] before calling chr(), and handle out-of-range input as an error instead of wrapping it.
  • If you are building a UTF-8 string from a code point rather than a raw byte, use mb_chr() instead of chr().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Providing an empty string is deprecated

Description

Calling ord() with an empty string is like calling it without an argument: it has nothing to work on.

Example

<?php

    ord('');

?>

Alternatives

  • Remove the call ord() on empty string.
  • Check that the length of the string passed to ord() is 1.
  • Ensure that the string is in latin1 encoding: multi-byte strings will also lead to an error.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See emptyStringWithOrd

Providing an object to argument #1 ($sessionhandler) which does not have the create_sid() method defined is deprecated

Description

create_sid() and validateId() currently live on the optional SessionIdInterface / SessionUpdateTimestampHandlerInterface, so a handler passed to session_set_save_handler() can implement SessionHandlerInterface alone and simply lack them; PHP silently falls back to its built-in session ID generation. Both methods are being folded into SessionHandlerInterface itself, so PHP 8.6 deprecates supplying a handler object that doesn’t define create_sid() — it will become mandatory in PHP 9.0.

Example

<?php

class SessionHandlerTester implements SessionHandlerInterface {
    public function close(): bool { return true; }
    public function destroy($id): bool { return true; }
    public function gc($max_lifetime): int|false { return 1; }
    public function open($path, $name): bool { return true; }
    public function read($id): string { return ''; }
    public function write($id, $data): bool { return true; }
    // create_sid() intentionally not implemented
}

session_set_save_handler(new SessionHandlerTester());
session_start();

?>

Alternatives

  • Implement a public create_sid(): string method on the session handler, generating an unpredictable, unique session ID.
  • Implement SessionIdInterface explicitly so the requirement is visible at the class declaration.

In more recent PHP versions, this error message is now :ref:providing-an-object-to-argument-#1-($sessionhandler)-which-does-not-have-the-validateid()-method-defined-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Providing an object to argument #1 ($sessionhandler) which does not have the validateId() method defined is deprecated

Description

validateId() currently lives on the optional SessionUpdateTimestampHandlerInterface, so a handler passed to session_set_save_handler() can implement only SessionHandlerInterface and lack it; with session.use_strict_mode enabled, PHP falls back to accepting any externally supplied session ID without validating it, weakening the protection strict mode is meant to provide. validateId() is being folded into SessionHandlerInterface itself, so PHP 8.6 deprecates supplying a handler object that doesn’t define it — it will become mandatory in PHP 9.0.

Example

<?php

class SessionHandlerTester implements SessionHandlerInterface {
    public function close(): bool { return true; }
    public function destroy($id): bool { return true; }
    public function gc($max_lifetime): int|false { return 1; }
    public function open($path, $name): bool { return true; }
    public function read($id): string { return ''; }
    public function write($id, $data): bool { return true; }
    // validateId() intentionally not implemented
}

session_set_save_handler(new SessionHandlerTester());
session_start();

?>

Alternatives

  • Implement a public validateId(string $id): bool method on the session handler that checks whether the given ID already exists in storage.
  • Implement SessionUpdateTimestampHandlerInterface (which also adds updateTimestamp()) explicitly so the requirement is visible at the class declaration.

In previous PHP versions, this error message used to be :ref:providing-an-object-to-argument-#1-($sessionhandler)-which-does-not-have-the-create_sid()-method-defined-is-deprecated.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Providing individual callbacks instead of an object implementing SessionHandlerInterface is deprecated

Description

session_set_save_handler() used to accept six to to nine distinct callables to configure the handler. In fact, that PHP native function was available even before PHP had objects support.

Nowadays, there still needs that many callables, but they are expected to be grouped in a class, and checked by the SessionHandlerInterface interface.

Example

<?php

 session_set_save_handler(
    session_open(...),
    session_close(...),
    session_read(...),
    session_write(...),
    session_destroy(...),
    session_gc(...),
    session_create_sid(...),
    session_validate_sid(...),
    session_update_timestamp(...)
);

?>

Alternatives

  • Refactor the callables into a class, add the SessionHandlerInterface implementation and use that class.

Readonly class %s cannot extend non-readonly class %s

Description

A readonly class cannot extends a non-readonly class; a non-readonly class cannot extends a readonly class. Both classes must be readonly or non-readonly to be able to extends one another. This is due to readonly being applied to all available properties, which is ambiguous with class hierarchies.

Example

<?php

class Foo
{
}

readonly class Bar extends Foo
{
}

?>

Literal Examples

  • Readonly class Foo cannot extend non-readonly class Bar

Alternatives

  • Make both classes readonly.
  • Make both classes non-readonly.
  • Make both classes non-readonly and apply readonly per properties.

Readonly class %s cannot use trait with a non-readonly property %s::$%s

Description

When a class is readonly, then even the properties added to the class from a trait have to be readonly. Since a trait cannot be readonly, like a class, then each of the properties in the trait, have to be readonly.

Also, note that PHP checks all the traits and the traits of the traits, for readonly properties.

Example

<?php

trait T {
	private $property;
}

readonly class X {
	use T;
}

?>

Literal Examples

  • Readonly class x cannot use trait with a non-readonly property t::$a

Alternatives

  • Remove the readonly on the class and apply to all each property in the class.
  • Make each of the property in the trait, and its dependencies, readonly.

Readonly property %s::$%s cannot have default value

Description

A readonly property is expected to be set once, and only once, at execution time. Then, it is not changed anymore.

A property, whose value is known at compilation time should probably be a constant.

Example

<?php

class T {
	public readonly int $i = 1;
}

?>

Literal Examples

  • Readonly property x::$i cannot have default value

Alternatives

  • Drop the readonly option.
  • Make the property a class constant.

Readonly property %s::$%s must have type

Description

A readonly property must be typed. It cannot be left without a type. In case of need of a wide range of types, use an union type, or the mixed keyword.

Example

<?php

class X {
    private readonly $property;
}

?>

Literal Examples

  • Readonly property X::$property must have type

Alternatives

  • Use the mixed type to explicitly type the property, but not commit to any constraint.
  • Use an union type to explicitly type the property, and commit to a restricted list of types.
  • Use the actual type for the property.
  • Remove the readonly option.

Recursion detected

Description

The compact function accepts an array of arguments. The function is actually recursive, and searches for everything recursively. This leads to potential infinite recursion, if the provided array contains a link to itself.

Example

<?php

$a = 1;
$arr1 = array('a', &$arr1);
try {
    var_dump(compact($arr1));
} catch (Error $e) {
    echo $e->getMessage() . \n;
}

?>

Alternatives

  • Flatten the array into one level only.
  • Remove the self references.
  • Do not use array known to host self references, such as $GLOBALS.

Redefinition of parameter $%s

Description

Parameters must all have distinct names in a method signature. Before PHP 7.0, no error was emitted, and the last parameter’s value was used. In PHP 7.0 and more recent, it is a compilation error.

Example

<?php

function foo($b, $b, $b) {}

?>

Literal Examples

  • Redefinition of parameter $b

Alternatives

  • Use all different names for the parameters.

ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists

Description

ReflectionClass::getConstant() returns false both when the requested constant does not exist and when the constant’s actual value is false, so the return value alone cannot tell the two cases apart. Calling it for a constant that does not exist is now deprecated in favour of an explicit existence check.

Example

<?php

class X {
    const FOO = 1;
}

$class = new ReflectionClass(X::class);
$value = $class->getConstant('BAR');
var_dump($value);

?>

Literal Examples

  • ReflectionClass::getConstant() for a non-existent constant is deprecated, use ReflectionClass::hasConstant() to check if the constant exists

Alternatives

  • Call ReflectionClass::hasConstant() first, and only call getConstant() once existence is confirmed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ReflectionClass::getConstant

ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, use ReflectionProperty::hasDefaultValue() to check if the default value exists

Description

ReflectionProperty::getDefaultValue() returns null both when the property genuinely defaults to null and when the property has no default value at all (such as an uninitialized typed property), so the return value alone cannot tell the two cases apart. Calling it for a property that has no default value is now deprecated in favour of an explicit existence check.

Example

<?php

class X {
    public int $prop;
}

$r = new ReflectionProperty(X::class, 'prop');
var_dump($r->getDefaultValue());

?>

Literal Examples

  • ReflectionProperty::getDefaultValue() for a property without a default value is deprecated, use ReflectionProperty::hasDefaultValue() to check if the default value exists

Alternatives

  • Call ReflectionProperty::hasDefaultValue() first, and only call getDefaultValue() once a default value is confirmed to exist.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ReflectionProperty::getDefaultValue

Requested precision of %d digits was truncated to PHP maximum of %d digits

Description

A decimal number is being represented as a string, with a precision which is above the precision available to PHP itself. Since no more data is available, the requested precision was not met.

Example

<?php

printf(%.988f,1.23456789e10);

?>

Literal Examples

  • Requested precision of 20 digits was truncated to PHP maximum of 14 digits

Alternatives

  • Reduce the requested precision, down to 54 maximum.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Required parameter $%s follows optional parameter $%s

Description

An optional parameter has a default value, while a required parameter doesn’t. In a method signature, PHP recommends to set the required parameters first, then the optional parameter.

When this is not the case, PHP is unable to understand if an argument has to be assigned to a parameter, or if it can be skipped, and assigned to the next required. When this happens, any required parameter makes previously defined parameter also required.

Example

<?php
	
function foo($a = 1, $b) {}
	
?>

Literal Examples

  • Required parameter $b follows optional parameter $b

Alternatives

  • Remove the default value of the early optional parameter.
  • Add a default value of the late required parameter.

In more recent PHP versions, this error message is now :ref:optional-parameter-$%s-declared-before-required-parameter-$%s-is-implicitly-treated-as-a-required-parameter.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See OptionalParameterLast

Required Trait %s wasn’t added to %s

Description

This error happens during name conflict resolution for traits. It means that one of the mentioned trait is not use in the code, and cannot be replaced or replacing another method. In the example below, the trait T2 is mentioned, but is not in the use command.

Example

<?php
trait T1 {
    function foo() {echo "T1\n";}
}
trait T2 {
        function foo() {echo "T2\n";}
}
class C {
    use T1 {
        T2::foo insteadof T1;
    }
}
?>

Literal Examples

  • Required Trait T2 wasn’t added to C

Alternatives

  • Add the missing trait to the class.
  • Remove the extra name resolution from the class.

Return type of %s::%s() should either be compatible with %s::%s(): mixed

Description

Native PHP interfaces, which define a type, expect the derived methods to use the same time. In particular, a mixed return type was added to some interfaces and must be available with child classes.

Since PHP 8.1, the mixed return type is now enforced, and a deprecated notice is displayed.

One alternative is to add the expected return type; a temporary solution is to the #[ReturnTypeWillChange] attribute. The attribute makes the warning disappear, but must be updated in the long run to keep in line with PHP recommendations.

This rule covers the following interfaces :

  • ArrayAccess
  • Countable
  • Exception
  • FilterIterator
  • Iterator
  • JsonSerializable
  • php_user_filter
  • SessionHandlerInterface.

Example

<?php

class MyJsonSerialize implements JsonSerialize { 
    function jsonserialize() : int {}
}

?>

Literal Examples

  • Return type of MyJsonSerialize::jsonserialize() should either be compatible with JsonSerialize::jsonserialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice

Alternatives

  • Use the correct return type for the methods from the interfaces.
  • Use the the #[ReturnTypeWillChange] to hide the error message.
  • Remove the interface from this class.
  • Remove the offending method.

Return value of %s%s%s() must %s%s%s, %s%s returned

Description

The type of the returned value must match the type of the method signature.

With strict_types, PHP refuses anything that is not compatible with the returned type: returning ‘123’ (123 as a string), or 123.00 (123 as float) is forbidden.

Without strict_types, PHP tries to convert the value to int, and only produces an error when it cannot.

Example

<?php

function foo() : int {
	return 'abc';
}
?>

Literal Examples

  • Return value of foo() must be int, string returned

Alternatives

  • Use a cast to force the type to the desired returntype.
  • Check the type before returning it.
  • Remove the return type.
  • Remove strict_types.

Returning a value from a constructor is deprecated

Description

new X always evaluates to the newly created instance, no matter what __construct() returns: any value returned from a constructor is discarded.

Since explicitly returning a value from __construct() is therefore always misleading dead code, PHP 8.6 deprecates it. A bare return; with no expression, used purely to exit the constructor early, remains unaffected.

Example

<?php

class X {
    public function __construct() {
        return 42;
    }
}

$x = new X;
var_dump($x);

?>

Literal Examples

  • Returning a value from a constructor is deprecated

Alternatives

  • Use a bare return; (with no expression) to exit the constructor early.
  • If you need to build and hand back an object based on some logic, use a static factory method instead of relying on new and a constructor return value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See constructorReturnDeprecated

Returning a value from a destructor is deprecated

Description

__destruct() is invoked automatically by PHP’s garbage collector when an object is about to be destroyed; nothing ever reads or uses its return value.

Since explicitly returning a value from __destruct() is therefore always dead code, PHP 8.6 deprecates it. A bare return; with no expression, used purely to exit the destructor early, remains unaffected.

Example

<?php

class X {
    public function __destruct() {
        return 42;
    }
}

$x = new X;
unset($x);

?>

Literal Examples

  • Returning a value from a destructor is deprecated

Alternatives

  • Use a bare return; (with no expression) to exit the destructor early.
  • Remove the return $value; statement; if you need to signal something to calling code, do it before the object is unset, not from the destructor.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See constructorReturnDeprecated

Returning bool from comparison function is deprecated, return an integer less than, equal to, or greater than zero

Description

usort() requires a callback function, that is used to put set the order in the array. This function must return three different values:

  • 1 if $a > $b
  • 0 if $a == $b
  • -1 if $a < $b

The return type should be the integer subset [1, 0, -1], and since there is no such type in PHP, the int type shall be used.

This is exactly compatible with the spaceship operator <=>.

Also, note that any positive integer is considered as 1, and any negative integer is considered as -1.

This applies to usort(), uasort(), uksort().

Not that without declare(strict_types=), the integer result of the callback is converted into a boolean, where 1 and -1 are both true. This may lead to strange results.

Example

<?php

function foo($a, $b): bool { return $a > $b; }

$array = [4, 2, 3, 0];

usort($array, foo(...));

?>

Alternatives

  • Use the int return type.
  • Remove the return type.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See sortClosureReturnType

Returning bool from comparison function is deprecated

Description

The comparison function should return 0, 1 or -1, and not just booleans. 1 means that $a > $b, -1 that $a < $b and 0 means that $a === $b. This is a richer information than boolean, and it also fits very well with the spaceship operator <=>.

Example

<?php

function mySort(int $a, int $b) : bool {
    return $a > $b;
}

$array = [1,2,3,4,5,6,7,8,9,10];
usort($array, mySort(...));

?>

Alternatives

  • Set the returntype of the comparison function to int.
  • Use the spaceship operator as possible.
  • Cast the result to integer.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See sortClosureReturnType

Returning by reference from a void function is deprecated

Description

The return type void means that no value is returned, not even NULL. This means that the & option has no value here. Since PHP 8.1, this is reported as deprecated.

In the end, it has no value to collect the returned value of a void function, reference or not.

Example

<?php

function &foo() : void { }

?>

Alternatives

  • Do not collect the returned valueo of a void function.
  • Remove the reference in the method definition.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See return_reference_on_void

Returning from a finally block is deprecated

Description

A return statement inside a finally block always wins: it replaces whatever the try or catch block was about to return, and it silently swallows any exception that was propagating out of the try. Unlike the other abrupt exits from a finally block, which PHP already forbids outright (break, continue and goto out of a finally are compile errors, and a throw automatically chains the discarded exception as $previous), return gave no indication that anything had been dropped.

PHP 8.6 deprecates this pattern. It remains legal for now, but the discarded return value or exception should be treated as a latent bug.

Example

<?php

function getConfig(): array {
    try {
        return loadConfig(); // may throw
    } finally {
        return []; // the exception, or the try's return value, is silently discarded
    }
}

?>

Literal Examples

  • Returning from a finally block is deprecated

Alternatives

  • Move the return statement out of the finally block, into the try or after it.
  • If the intent is to override the result deliberately, do so explicitly outside the finally block so the discarded value or exception is visible.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Previously, returning from a finally block silently discarded any pending exception or return value from the try/catch, with no warning. As of PHP 8.6, doing so emits a deprecation notice.](Previously, returning from a finally block silently discarded any pending exception or return value from the try/catch, with no warning. As of PHP 8.6, doing so emits a deprecation notice.)

Returning null from %s::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead

Description

The __debugInfo() magic method controls what var_dump() displays for instances of the class. It must return an array; historically, returning null was also tolerated and treated the same as an empty array (hiding all properties).

This message is emitted at class-declaration time whenever __debugInfo() is declared with a return type that allows null (?array, array|null, and similar), regardless of whether the method is ever actually called or ever really returns null. Since null and [] are handled identically, keeping the return type nullable serves no purpose, so PHP 8.6 deprecates it in favor of a strict array return type.

This is a compile-time counterpart to “Returning null from %s::__debugInfo() is deprecated, return an empty array instead”, which instead fires at call time for a method that has no return type declared at all but returns null anyway.

Example

<?php

class X {
    public function __debugInfo(): ?array {
        return null;
    }
}

var_dump(new X);

?>

Literal Examples

  • Returning null from X::__debugInfo() is deprecated, make the return type non-nullable and return an empty array instead

Alternatives

  • Declare __debugInfo(): array instead of __debugInfo(): ?array (or array|null).
  • Return an empty array [] instead of null from __debugInfo().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Returning null from %s::__debugInfo() is deprecated, return an empty array instead

Description

The __debugInfo() magic method allows a class to customize what var_dump() displays for its instances. When this method returns null, PHP has historically treated it as an empty array, but the behavior was inconsistent.

Since PHP 8.4, returning null from __debugInfo() is deprecated. This deprecation ensures consistent behavior and explicit return types.

Returning an empty array [] achieves the same effect (hides all properties from var_dump()) while being type-safe and unambiguous.

Example

<?php

class X {
    public function __debugInfo(): ?array {
        return null;
    }
}

var_dump(new X);

?>

Literal Examples

  • Returning null from X::__debugInfo() is deprecated, return an empty array instead

Alternatives

  • Return an empty array [] instead of null from __debugInfo().
  • Remove the __debugInfo() method entirely if you want the default var_dump() behavior.
  • Return the array of properties you want to display: return ['key' => $this->value];.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See debugInfoCannotReturnNull

Security level must be one of “noAuthNoPriv”, “authNoPriv”, or “authPriv”

Description

The third argument of snmp3_get() must be one of the following values, “noAuthNoPriv”, “authNoPriv”, or “authPriv”. Case is important. There are not constants to for these values.

Example

<?php

try {
    var_dump(snmp3_get($hostname, $community, '', '', '', '', '', '.1.3.6.1.2.1.1.1.0'));
} catch (\ValueError $e) {
    echo $e->getMessage() . \PHP_EOL;
}

?>

Alternatives

  • Use one of the three possible values.

Security protocol must be one of “AES128”, or “AES E_ERROR

Description

The fourth argument of snmp3_get() must be one of the following values, “AES128”, or “AES”.

The DES protocol must be inactive to see this error message. Otherwise, a distinct message is displayed.

Case is important. There are not constants to for these values.

Example

<?php

try {
    var_dump(snmp3_get($hostname, $community, '', 'protocol', '', '', '', '');
} catch (\ValueError $e) {
    echo $e->getMessage() . \PHP_EOL;
}

?>

Alternatives

  • Use one of the two possible values.

Security protocol must be one of “DES”, “AES128”, or “AES E_ERROR

Description

The fourth argument of snmp3_get() must be one of the following values, DES, AES128, or AES.

The DES protocol must be active to see this error message. Otherwise, a distinct message is displayed.

Case is important. There are not constants to for these values.

Example

<?php

try {
    var_dump(snmp3_get($hostname, $community, '', 'protocol', '', '', '', '');
} catch (\ValueError $e) {
    echo $e->getMessage() . \PHP_EOL;
}

?>

Alternatives

  • Use one of the three possible values.

Serialization of %s is not allowed, override __serialize() and __unserialize() to implement it

Description

Some internal classes hold state, such as a connection handle or a resource, that cannot be meaningfully turned into a string and restored later. To prevent silent data loss or unusable objects after unserialize(), PHP flags these classes as not serializable by default. Since PHP 7.4, a class can opt back in by implementing the __serialize() and __unserialize() magic methods, giving full control over what state is actually persisted and how it is restored. Trying to serialize() an instance of such a class, or of a subclass that does not add these methods, throws this exception.

Example

<?php

$pdo = new PDO('sqlite::memory:');

$data = serialize($pdo);

?>

Literal Examples

  • Serialization of PDO is not allowed, override __serialize() and __unserialize() to implement it

Alternatives

  • Create a subclass that implements __serialize() and __unserialize() to control exactly which state is persisted.
  • Avoid serializing the object directly; store only the data needed to recreate it, then reconstruct it manually.

In more recent PHP versions, this error message is now :ref:unserialization-of-%s-is-not-allowed,-override-__serialize()-and-__unserialize()-to-implement-it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Session callback must have a return value of type bool, %s returned

Description

The callbacks registered through session_set_save_handler() (open, close, read, write, destroy, gc, etc.) are expected to return a value of type bool to report success or failure, matching the signatures declared by SessionHandlerInterface.

Some older session handlers followed the pre-PHP 7 convention of C-style save handlers, returning an integer (0 for success, a negative value such as -1 for failure) instead of true/false. PHP still accepts 0 and -1 for backward compatibility, but as of PHP 8.0.0 it emits a deprecation notice naming the actual type/value returned; any other non-bool return value triggers a TypeError instead.

Example

<?php

session_set_save_handler(
    open: fn (string $path, string $name): bool => true,
    close: fn (): bool => true,
    read: fn (string $id): string => '',
    // Legacy convention: 0 for success, -1 for failure,
    // instead of returning a real bool.
    write: fn (string $id, string $data): int => 0,
    destroy: fn (string $id): bool => true,
    gc: fn (int $max_lifetime): int => 0,
);

session_start();

?>

Alternatives

  • Make every session handler callback explicitly return true or false.
  • Implement SessionHandlerInterface on a dedicated class instead of passing loose callables, so the return types are enforced.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See session_set_save_handler

session.sid_bits_per_character INI setting is deprecated

Description

session.sid_bits_per_character used to control how many bits of entropy each character of a generated session ID encodes (from 4, hexadecimal, up to 6, a larger custom alphabet), in combination with session.sid_length.

Letting this be configurable made it possible to end up with weak, easily-guessable session IDs if the values were lowered, without much practical benefit from raising them either. PHP 8.4 fixes the format to a 32-character hexadecimal session ID (4 bits per character) and deprecates the directive; it is only emitted when the value is set to something other than the fixed default of 4.

Example

<?php

ini_set('session.sid_bits_per_character', '5');

?>

Alternatives

  • Remove session.sid_bits_per_character from php.ini and from the code; PHP now always uses a 32-character hexadecimal session ID.

In more recent PHP versions, this error message is now :ref:session.sid_length-ini-setting-is-deprecated.

session.sid_length INI setting is deprecated

Description

session.sid_length used to control the number of characters in a generated session ID, in combination with session.sid_bits_per_character.

Letting this be configurable made it possible to end up with weak, easily-guessable session IDs if the value was lowered too much. PHP 8.4 fixes the format to a 32-character session ID and deprecates the directive; it is only emitted when the value is set to something other than the fixed default of 32.

Example

<?php

ini_set('session.sid_length', '26');

?>

Alternatives

  • Remove session.sid_length from php.ini and from the code; PHP now always uses a 32-character session ID.

In previous PHP versions, this error message used to be :ref:session.sid_bits_per_character-ini-setting-is-deprecated.

Set access level of %s::$%s must be %s (as in class %s)%s

Description

This error is specific to asymmetric visibility. A property may expose a wider visibility for reading than for writing, for example public protected(set) string $foo, which can be read from anywhere but only written from within the class or its subclasses.

When a child class redeclares such a property, the write (set) visibility it declares must be the same as, or weaker (more permissive) than, the one inherited from the parent. It cannot be narrowed. In the example, the parent grants write access to protected(set), but the child tries to restrict it further to private(set), which is forbidden.

The same error is raised, with an omitted access level instead of a named one, when the parent property has no explicit set-visibility restriction at all (a plain read/write property, or a hooked virtual property whose get hook exists but set hook does not restrict visibility): in that case, the child is not allowed to introduce any set-visibility restriction, since that would also be a narrowing of what the parent allows.

A property declared readonly implicitly behaves as write-once with an asymmetric set visibility, so this error can also surface when a plain or hooked property overrides, or implements, a readonly property with looser write access.

Example

<?php

class A {
    public protected(set) string $foo;
}

class B extends A {
    public private(set) string $foo;
}

?>

Literal Examples

  • Set access level of B::$foo must be protected(set) (as in class A) or weaker
  • Set access level of B::$foo must be omitted (as in class A)

Alternatives

  • Use the same set-visibility keyword as the parent class (or omit it, if the parent has none).
  • Widen the set-visibility of the child property so that it is the same as, or weaker than, the parent’s.
  • Remove the asymmetric visibility from the child property altogether.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Set type of %s::$%s must be supertype of %s (as in %s %s)

Description

A property hooked with a set hook can accept a wider range of values than its declared (get) type, since the set hook is free to convert or narrow whatever it receives before storing it. In the example, I::$prop accepts both int and string on write, even though it only ever reads back as string.

When a class overrides such a property, whether by extending a parent class or implementing an interface, the type accepted on write by the new declaration must remain a supertype of (or equal to) the type accepted by the original declaration. It must not be narrowed.

In the example, C::$prop is a plain property, so it can only be assigned values of its own declared type, string. This is narrower than the int|string accepted by I::$prop’s set hook, so code that relied on I’s contract to pass an int to $prop would break. Consequently, PHP rejects the composition.

Example

<?php

interface I {
    public string $prop {
        set(int|string $value);
    }
}

class C implements I {
    public string $prop;
}

?>

Literal Examples

  • Set type of C::$prop must be supertype of string|int (as in interface I)

Alternatives

  • Give the child property (or its set hook parameter) a type that is the same as, or a supertype of, the type accepted by the parent’s set hook.
  • Add an explicit set hook to the child property, accepting the same or a wider type than the parent.
  • Narrow the type accepted by the parent’s set hook instead, if the wider type is not actually needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

setlocale() expects exactly 2 arguments when argument #2 ($locales) is an array, %d given

Description

setlocale() accepts a locale to try either as one or more separate string arguments (each tried in turn until one succeeds), or as a single array of candidate locale strings passed as $locales. Since PHP 8.6, mixing the two forms in the same call, an array followed by further trailing string arguments, is rejected outright: when $locales is an array, it must be the only argument supplied after $category.

Example

<?php

setlocale(LC_ALL, ['en_US.UTF-8', 'C'], 'fr_FR.UTF-8');

?>

Literal Examples

  • setlocale() expects exactly 2 arguments when argument #2 ($locales) is an array, 3 given

Alternatives

  • Pass the candidate locales either as separate string arguments (setlocale($category, $a, $b, …)) or as a single array ($category, [$a, $b, …]), but not both in the same call.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, this combination was silently accepted: PHP tried each candidate in the array first, then went on to also try any trailing string arguments as further candidate locales, instead of rejecting the mixed call.](Prior to PHP 8.6, this combination was silently accepted: PHP tried each candidate in the array first, then went on to also try any trailing string arguments as further candidate locales, instead of rejecting the mixed call.)

Spread operator is not supported in assignments

Description

The spread operator cannot be used with the list() operator. It may be used to spread an array into arguments, but it is not possible to do the same when assigning elements inside an array.

Example

<?php

[...$x] = [1, 2, 3];

list(...$x) = array(1, 2, 3);

[$x[0], , $x['a']] = [1, 2, 3];

?>

Alternatives

  • Write the full list of targets in the list operator: it might be array elements, and the array nor the elements needs to pre-exists.

SQLite3Result cannot be directly instantiated

Description

Sqlite3Result is returned after executing a SQL query on a Sqlite3 database, with such method as query or execute.

Example

<?php

new Sqlite3Result();

?>

Alternatives

  • Call a valid query to obtain an object of that class.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

static“ is not allowed in compile-time constants

Description

“New in initializers” (PHP 8.1) allows new expressions in constant-expression contexts, such as default parameter values, as long as the class being instantiated is fixed and unambiguous: a literal class name, self, or parent. static refers to the class actually used at call time (late static binding), which can differ for every subclass, so it cannot be resolved once and for all at the point the initializer is compiled, and is rejected.

Example

<?php

class Point {
	public function __construct(
		public readonly self $origin = new static()
	) {}
}

?>

Alternatives

  • Use self if the intent is to always instantiate the declaring class.
  • Move the instantiation into the constructor or method body instead, where late static binding works normally: $origin ??= new static();

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Static function %s%s%s() cannot be abstract

Description

This error could not be reproduced so far. Help us by sending us any generating code.

Example


Literal Examples

  • Static function foo() cannot be abstract

Alternatives

Static property %s::$%s cannot be readonly

Description

Static properties cannot use the readonly option. readonly only support normal properties, and not static properties.

Example

<?php

class X {
    public static readonly int $property;
}

?>

Literal Examples

  • Static property X::$property cannot be readonly

Alternatives

  • Remove the readonly option.
  • Turn the static property into a normal property.

Static property may not have asymmetric visibility

Description

Asymmetric visibility is only applicable to object properties, not static properties.

Example

<?php
class X {
    static private(set) $p = 1;
}
?>

Alternatives

  • Make the property non-static.
  • Remove the asymmetric visibility.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

static::" is not allowed in compile-time constants

Description

Class constants are meant to hold a single, fixed value shared identically by the declaring class and every subclass that inherits it. Referencing static:: inside a constant expression would make the value depend on late static binding, i.e. on whichever subclass actually reads it, which contradicts a constant’s fixed nature, so PHP rejects it at compile time.

Example

<?php

class Base {
	const A = 1;
	const B = static::A * 2;
}

?>

Alternatives

  • Use self:: instead if the intent is to always refer to the declaring class’s own member.
  • Compute the value in a static method instead of a constant.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

static::class cannot be used for compile-time class name resolution

Description

static::class resolves to the class name of whichever subclass is actually in scope at runtime, through late static binding. A class constant, on the other hand, is resolved once and shared identically by the declaring class and every class that inherits it, so it cannot hold a value that is meant to vary per subclass. self::class is accepted in the same spot because it never varies.

Example

<?php

class Base {
	const NAME = static::class;
}

?>

Alternatives

  • Use self::class if a fixed class name is acceptable.
  • Expose it through a method instead: public static function name(): string { return static::class; }.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

stream context option error_mode must be of type StreamErrorMode

Description

PHP 8.6 adds a stream context option, error_mode, that controls how errors raised by a stream operation are reported. It must be one of the cases of the StreamErrorMode enum: StreamErrorMode::Error (the default, standard PHP warnings/notices), StreamErrorMode::Exception (throw a StreamException for terminating errors), or StreamErrorMode::Silent (suppress error output entirely).

Passing anything other than a StreamErrorMode case, such as a plain string, throws a TypeError when the stream operation reads the option, instead of the option being silently ignored.

Example

<?php

$context = stream_context_create([
    'stream' => ['error_mode' => 'exception'],
]);

file_get_contents('https://example.invalid/', false, $context);

?>

Literal Examples

  • stream context option ‘error_mode’ must be of type StreamErrorMode

Alternatives

  • Pass one of the StreamErrorMode enum cases, e.g. StreamErrorMode::Exception, instead of a string or other value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

stream context option error_store must be of type StreamErrorStore

Description

PHP 8.6 adds a stream context option, error_store, that controls which errors raised during a stream operation are kept for later retrieval. It must be one of the cases of the StreamErrorStore enum: Auto (the default, decides based on error_mode), None, NonTerminating, Terminating, or All.

Passing anything other than a StreamErrorStore case throws a TypeError when the stream operation reads the option; PHP then falls back to deciding the store mode automatically from error_mode, but still reports the misuse.

Example

<?php

$context = stream_context_create([
    'stream' => ['error_store' => 'all'],
]);

file_get_contents('https://example.invalid/', false, $context);

?>

Literal Examples

  • stream context option ‘error_store’ must be of type StreamErrorStore

Alternatives

  • Pass one of the StreamErrorStore enum cases, e.g. StreamErrorStore::All, instead of a string or other value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

stream error handler must be a valid callback, %s

Description

PHP 8.6 adds a stream context option, error_handler, that receives the StreamError[] produced by a stream operation through a callback with the signature function(array $errors): void.

If the supplied value is not actually callable, PHP throws a TypeError whose message is completed with the specific reason returned by the callable check, for example “array must have exactly two elements” or “function … does not exist”.

Example

<?php

$context = stream_context_create([
    'stream' => ['error_handler' => 'this is not a callback'],
]);

file_get_contents('https://example.invalid/', false, $context);

?>

Literal Examples

  • stream error handler must be a valid callback, no array or string given
  • stream error handler must be a valid callback, function ‘doesNotExist’ not found or invalid function name

Alternatives

  • Pass a real callable (closure, function name, or [object, method] array) as the error_handler stream context option.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Stream filter %s is never seekable

Description

PHP 8.6 fixes a long-standing inconsistency (bug #49874) between fseek()/ftell() and stream filters: seeking a stream now checks whether every filter currently attached to the affected chain (read or write) can actually tolerate the requested seek, instead of blindly repositioning the stream and leaving filtered/compressed data out of sync with the raw underlying position.

Some filters, such as zlib.deflate and zlib.inflate, accept a write_seek_mode filter parameter controlling how seeks on their write side are handled: 'preserve' (the default, always seekable), 'reset' (seekable only back to the start), or 'strict' (never seekable once data has started flowing through the filter). With 'strict' in effect, any seek attempt now emits this warning and fails, instead of silently succeeding and corrupting the filtered output.

Example

<?php

$stream = fopen('php://temp', 'r+');
fwrite($stream, str_repeat('a', 100));
rewind($stream);

stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_WRITE, ['write_seek_mode' => 'strict']);

fseek($stream, 0);

?>

Literal Examples

  • Stream filter zlib.deflate is never seekable

Alternatives

  • Don’t seek a stream whose filter chain was configured with write_seek_mode => ‘strict’, or use ‘preserve’/‘reset’ instead if the stream genuinely needs to be seekable.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, fseek() did not consult filter seekability at all: seeking a stream with filters attached always appeared to succeed, even when it left the filter’s internal state inconsistent with the new stream position.](Prior to PHP 8.6, fseek() did not consult filter seekability at all: seeking a stream with filters attached always appeared to succeed, even when it left the filter’s internal state inconsistent with the new stream position.)

Stream filter %s is seekable only to start position

Description

PHP 8.6 fixes a long-standing inconsistency (bug #49874) between fseek()/ftell() and stream filters: seeking a stream now checks whether every filter attached to the affected chain can actually tolerate the requested seek, instead of blindly repositioning the stream.

Reading through a decompression filter such as zlib.inflate (which zlib.deflate also uses on its read side) can always be restarted from position 0, since that simply means decompressing the underlying data again from the beginning. But it cannot jump to an arbitrary byte offset elsewhere in the stream, since that offset has no meaning inside the compressed byte stream. Seeking anywhere other than back to the very start now emits this warning and fails, instead of repositioning the stream to a location that no longer matches what has actually been decompressed.

Example

<?php

$stream = fopen('php://temp', 'r+');
fwrite($stream, str_repeat('a', 100));
rewind($stream);

stream_filter_append($stream, 'zlib.deflate', STREAM_FILTER_READ);

fread($stream, 10);
fseek($stream, 5, SEEK_CUR);

?>

Literal Examples

  • Stream filter zlib.deflate is seekable only to start position

Alternatives

  • Only rewind a stream read through such a filter back to position 0 (e.g. with rewind()); don’t seek to an arbitrary offset while the filter is attached.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, fseek() did not consult filter seekability at all: seeking a stream with a decompression filter attached always appeared to succeed, even when the requested offset had no valid meaning for the filter.](Prior to PHP 8.6, fseek() did not consult filter seekability at all: seeking a stream with a decompression filter attached always appeared to succeed, even when the requested offset had no valid meaning for the filter.)

Stream filter seeking for %s failed

Description

PHP 8.6 fixes a long-standing inconsistency (bug #49874) between fseek()/ftell() and stream filters: seeking now defers to each attached filter’s own seek logic instead of blindly repositioning the stream. A custom filter registered via stream_filter_register() can implement a seek(int $offset, int $whence, int $chain): bool method to participate in that decision; if it returns false, the requested seek is now treated as failed and this warning is emitted, instead of the stream silently repositioning while the filter’s own internal state (e.g. a decompression buffer) drifted out of sync.

The %s placeholder in this message is always the literal string “user-filter” for any custom, PHP-defined filter class, regardless of the name it was registered under with stream_filter_register(); only PHP’s own built-in filters (like zlib.inflate) report their own name.

Example

<?php

class DenySeekFilter extends php_user_filter
{
    public function filter($in, $out, &$consumed, $closing)
    {
        while ($bucket = stream_bucket_make_writeable($in)) {
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }

    public function seek(int $offset, int $whence, int $chain): bool
    {
        return false;
    }
}

stream_filter_register('deny.seek', DenySeekFilter::class);

$stream = fopen('php://temp', 'r+');
fwrite($stream, 'hello world');
rewind($stream);

stream_filter_append($stream, 'deny.seek');

fseek($stream, 3);

?>

Literal Examples

  • Stream filter seeking for user-filter failed

Alternatives

  • Make a custom filter’s seek() method return true for any offset it can actually honor, or omit the method entirely to let all seeks succeed as before.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See [Prior to PHP 8.6, a custom filter’s onSeek() return value had no effect on fseek(): the stream was always repositioned regardless of what the filter reported.](Prior to PHP 8.6, a custom filter’s onSeek() return value had no effect on fseek(): the stream was always repositioned regardless of what the filter reported.)

strict_types declaration must be the very first statement in the script

Description

This error appears when the declare statement is not the first statement in the file.

It appears even when non-executing statement are placed before it, such as forgotten characters before the opening tag, any kind of operations in PHP commands, including definitions, namespaces, etc.

Other declare() calls may appears before the strict_types one, though. Also, PHP uses this error with the other declare statement, such as ticks or encoding. They are very rare though.

Example

Here<?php

$a = 1;
declare(strict_types = 1);

?>

Alternatives

  • Check if any characters are left before the opening PHP tag.
  • Move the declare after the PHP opening tag.

strict_types declaration must be

Description

This is the same placement rule documented in full under strict_types declaration must be the very first statement in the script: the declare(strict_types = ...) pragma changes how the whole file is compiled, so PHP must see it before compiling anything else. Here, the namespace statement, itself harmless, is still a statement, and it pushes the declare() out of first position.

Only a preceding declare() call (for ticks or encoding) is tolerated before it; any other statement is not.

Example

<?php

namespace App;

declare(strict_types = 1);

?>

Literal Examples

  • strict_types declaration must be the very first statement in the script

Alternatives

  • Move the declare(strict_types = 1) statement to be the very first statement in the file.

In more recent PHP versions, this error message is now :ref:strict_types-declaration-must-be-the-very-first-statement-in-the-script.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

strict_types declaration must have 0 or 1 as its value

Description

The strict_types pragma is a switch: 0 keeps the usual weak typing (with type coercion for scalar type declarations), and 1 turns on strict typing for the current file. No other value makes sense, so PHP only accepts the literal integers 0 and 1; anything else, including true, false, or any other number, is rejected.

Example

<?php

declare(strict_types = 2);

?>

Literal Examples

  • strict_types declaration must have 0 or 1 as its value

Alternatives

  • Use 1 to enable strict typing, or 0 to keep weak typing.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

strict_types declaration must not

Description

declare() supports a block form for most directives, such as declare(ticks = 1) { ... }, which scopes the setting to the code inside the block. strict_types is different: it is a compile-time, whole-file setting, not something that can be toggled for a portion of the script. Because of that, the block form is rejected outright.

The full message reads: strict_types declaration must not use block mode.

Example

<?php

declare(strict_types = 1) {
    var_dump(strlen('abc'));
}

?>

Literal Examples

  • strict_types declaration must not use block mode

Alternatives

  • Remove the curly braces, and use declare(strict_types = 1); as a simple statement.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

strlen(): Passing null to parameter #1 ($string) of type string is deprecated

Description

strlen() calculates the length of a string. It only works on strings, and, in particular, cannot compute the length of the null value.

Example

<?php

$s = null;
print strlen($s); 

?>

Alternatives

  • Process null in a separate branch of code.
  • Convert null to the empty string before using strlen().

Switch statements may only contain one default clause

Description

The switch expression uses cases and a default entry. Cases are matched against the parameter variable, and when all of them fail, the default case (sic) is used. This also means that there can be only one defaut entry, as it will be used after all the cases.

When several default cases are spotted, PHP stops compilation.

Note that there is no error message for multiple identical cases: in such situations, the first one is used.

Example

<?php

switch($a) {
    default:
    default: 
}

?>

Alternatives

  • Remove all defaults but one.

syntax error, unexpected ')', expecting '='

Description

list() must appear on the left side of an assignation. It will be filled with the values in the array of the right side.

Example

<?php

var_dump(list(1,2,3));

?>

Alternatives

  • Add a = sign to the right of the list() call, and then, add an array on the right.
  • Turn the list() into a [] short syntax. This might change the meaning, as, in this case, list() becomes an array.

syntax error, unexpected ‘)’, expecting ‘|’ or variable (T_VARIABLE)

Description

Until PHP 8.0, exceptions always had to be named, with a variable.

Here, the error message is signaling that it expected another exception to catch, separated from the first one by a |, or a variable name.

Example

<?php

try {
    
} catch (E) {}

?>

Alternatives

  • Add a variable name to the catch clause.
  • Add another exception to catch, and then a name to the catch clause.
  • Upgrade to PHP 8.0 or more recent.

syntax error, unexpected ‘)’, expecting variable (T_VARIABLE)

Description

This error is related to the support the trailing comma in function calls: in PHP 7.4, it is allowed to add a final comma at the end of the arguments list, and yet, not provide an extra argument.

Example

<?php

function foo($a,
             $b,
             $c) { echo __METHOD__; }

echo foo(1,
         2,
         3,
         );

?>

Alternatives

  • Upgrade to PHP 7.4.
  • Remove the trailing comma.

syntax error, unexpected ‘,’

Description

Commas are used as a separator in lists of items, such as parameters, arguments, elements of an array. When such list is supposed to have only one element, the syntax error appears.

This happens with switch, match(), if(), or parenthesis, which all allow one expression, not two, although they might be confused with a function call.

It also happens with curly braces, which uses semi-colon ; as a separator.

The unexpected , appears when there is nothing between separators: for example, an empty argument, or a missing variable in a global call. The only situation where it is acceptable is inside a list() expression.

Example

<?php

// only one expression for switch, parenthesis, etc.
switch(2,3);
(1,2);

// blocks use ; as separator.
{3,4}

// comma must separate something
global $a,, $b;

?>

Alternatives

  • Check if the expression accepts more than one expression.
  • Review commas directly inside a curly braces block.

syntax error, unexpected ‘-’, expecting ‘=’

Description

When defining a constant, the constant name must be valid. It must be satisfying the following regex: /[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/. When an unexpected character appears, it yields this errors, mentioning the erroneous character first.

This error appears for global constant, written with const or for class constants, inside a class.

The unexpected character may have a lot of variations, in particular any non-letter or non-figure characters. Check the regex for more options.

Example

<?php

const A-B = 1;

?>

Alternatives

  • Remove the - in the constant name.
  • Remove the unexpected character in the constant name.
  • Remove the constant definition.

syntax error, unexpected ‘::’, expecting ‘(’

Description

This is a situation where a new keyword degrades a previously valid syntax. match is a new keyword in PHP 8.0, for the eponymous command. It cannot be used as a class name, a function name, or a global constant, as before.

By extension, the match keyword cannot be used in static object notations, such as calling a constant, or a static method or property.

This error may arise with other keywords, for similar reasons.

Example

<?php

echo Match::A;

?>

Alternatives

  • Rename the match class to a non-keyword name.

syntax error, unexpected ‘::’ (T_PAAMAYIM_NEKUDOTAYIM), expecting ‘;’ or ‘,’

Description

Using the static class syntax directly on an interpolated string was not possible until PHP 8.0. Until then, it reported a syntax error.

Example

<?php

class Bar {
    static function foo() {}
    static $property = 3;
    const C = 4;
}

$a = "ar";
echo "B$a"::foo();
echo "B$a"::$property;
echo "B$a"::C;

?>

Alternatives

  • Upgrade to PHP 8.0 or more recent.
  • Store the class name in a variable, and use that variable instead of the direct string.

syntax error, unexpected ‘;’, expecting ‘[’

Description

The & reference operator turns a value into a reference. It works with data containers, such as variables, properties or array elements. It doesn’t work on literal constants.

The error message suggestion to use extra operators such as [ leads to a distinct error: Cannot use temporary expression in write context.

Example

<?php

$a = &E_ALL;

const B = [1,2,3];
//Cannot use temporary expression in write context
$c = &B[2]; 

?>

Alternatives

  • Store the constant in a variable, and make the reference on the variable.
  • Use constants by value, not by reference.

In more recent PHP versions, this error message is now :ref:syntax-error,-unexpected-token-";",-expecting-"->"-or-"?->"-or-"{"-or-"[".

syntax error, unexpected ‘;’, expecting ‘{’

Description

The error message comes from the possibility to use new lines inside fully qualified names, that was possible until PHP 8.0.

Example

<?php

    \A 
                           \B 
                           \C
                           ;

?>

Alternatives

  • Remove the new lines and whitespaces inside a fully qualified name.

syntax error, unexpected ‘[’, expecting ‘;’ or ‘,’

Description

Using the array syntax directly on an interpolated string was not possible until PHP 8.0. Until then, it reported a syntax error.

Example

<?php

$a = 'foo';
echo bar$a[4]; // display f

?>

Alternatives

  • Upgrade to PHP 8.0 or more.
  • Put the string in a variable first.

syntax error, unexpected ‘elseif’

Description

The elseif must follow a if structure. It cannot be used alone, not be used after a else clause.

Example

<?php

// elseif cannot be standalone 
elseif ($a === 1) {
    echo 2;
}

// else has closed the if structure, not more elseif allowed
if ($condition) {}
else {} 
elseif ($a === 1) {
    echo 2;
}

// the endif; has already closed the if structure.
if ($condition):

endif;
elseif ($a === 1) :
    echo 2;
endif;

?>

Alternatives

  • Ensure that there is a previous if structure, with one then block, and optionally, other elseif block.
  • Ensure that there is no previous else clause.
  • Ensure that there is no previous endif keyword.

syntax error, unexpected ‘match’

Description

This error is related to match being a PHP keyword. Since PHP 8.0, it cannot be used anymore as a class or interface name. When moving from PHP 7 to 8, any traditional usage of match where a class name is expected shall produce such an error.

In the illustrations, no more details are provided about the reason why match is not allowed. Other situation may provide better hints.

This error applies to all PHP keywords. match is only the most common, as it is a new PHP 8.0 keyword.

Example

<?php

// Cannot use Match here.
interface X extends Match { }

// Cannot use Match here.
class Y implements Match { 

    // Cannot use Match here.
    use Match;
}

?>

Alternatives

  • Rename Match to something that is not a PHP keyword.
  • Stay on PHP 7.x.

syntax error, unexpected ‘throw’ (T_THROW)

Description

throw is not an expression until PHP 8.0. Until then, it cannot be used as part of another expression, such as the left part of or, an argument, or inside parenthesis.

After PHP 8.0, one could use it as part of an expression.

Example

<?php

$x ?? throw new \Exception('Missing value for x');

?>

Alternatives

  • Upgrade to PHP 8.0 or more recent.
  • Convert the or to an ifthen structure.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See throwIsAnExpression

syntax error, unexpected ‘{’

Description

This error arise when the old curly braces syntax is used to access an element in an array. This syntax was deprecated in PHP 7.x and removed entirely in 8.0. It also was left as a syntax error since PHP 8.3.

Example

<?php

$array[1]{0};

?>

Alternatives

  • Use the square brackets to access array elements.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected ‘|’, expecting variable (T_VARIABLE)

Description

Union types were introduced in PHP 8.0: union type allows the specification of several distinct types, separated by a | pipe character. Until PHP 8.0, types were immediately followed by the variable or property name.

Example

<?php

class X {
    private int|float $property;
}

function foo(int|float $property) {}


?>

Alternatives

  • Upgrade to PHP 8.0.
  • Find a common supertype to the two (or more) involved types.
  • Remove all types.

syntax error, unexpected end of file

Description

The unexpected end of file happens when PHP has not finished parsing a file, and still expected a few more tokens to complete it.

Usually, this means that not enough code was provided, or also, that some code instruction were not completed as expected.

In the example here, the expression is completed with a semi-colon, or a closing PHP tag. Both would conclude the expression, and the script, but they are not available.

Example

<?php

$x = 1

Alternatives

  • Make sure all expression are completed.

syntax error, unexpected fully qualified name “%s”, expecting “function” or “const”

Description

There should not be any fully qualified name inside the body of a class, enumeration, trait or interface. Names are used for methods or constants, or with the use expression, to import a trait.

Example

<?php

class X {
    \A;
}

?>

Alternatives

  • Add the use keyword before the name to import a trait.
  • Add the function keyword before the name to make it a method, although there should not be any \ in the method name.
  • Add the const keyword before the name to make it a constant, although there should not be any \ in the constant name.
  • Add the #[ keyword before the name to make it an attribute.

syntax error, unexpected fully qualified name “%s”, expecting “function”

Description

This error appears when a fully qualified name is used in the body of a class, (or any CITE).

Example

<?php

class X {
    \A\B;
}

?>

Alternatives

  • Remove the standalone name.
  • Add the use keyword before the standalone name, to import a related trait.

syntax error, unexpected fully qualified name “%s”, expecting “{”

Description

Until PHP 8.0, it was possible to include spaces or new lines in a namespace. They would be ignored later, but parsed and handled that way.

In PHP 8.0, this is not possible anymore.

Example

<?php

namespace Vendor
\XXX;

echo 1;

?>

Literal Examples

  • syntax error, unexpected fully qualified name “\XXX”, expecting “{”

Alternatives

  • Make namespaces one string, without new lines or any spaces.

syntax error, unexpected fully qualified name “%s”

Description

This error appears when new lines are introduced inside a namespace. This was possible syntax until PHP 8.0, but not anymore.

Example

<?php

// constant
    \A 
                           \B 
                           \C
                           ;
                           
?>

Alternatives

  • Remove the new lines and whitespaces from the namespace.

syntax error, unexpected identifier “%s”, expecting “(”

Description

After the function keyword and the function’s name, PHP expects the opening parenthesis of the argument list. Here, a second identifier was found instead, which usually means an extra word was typed, or a comma or a return-type colon was forgotten between two declarations.

Example

<?php

function foo bar() {}

?>

Literal Examples

  • syntax error, unexpected identifier “bar”, expecting “(”

Alternatives

  • Remove the extra identifier, keeping only the function name.
  • If a return type was intended, add a colon before it: function foo(): bar {}.
  • If two functions were meant to be declared, close the first one and start a new function statement.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected identifier “%s”, expecting “)”

Description

This error appears an argument is already a complete expression, yet a new identifier appears after it. Within a method call, this could have been the end of the call itself, or an expression error.

Example

<?php

foo(a: 1 b: 2);

foo(a: 1 c);

?>

Literal Examples

  • syntax error, unexpected identifier “b”, expecting “)”

Alternatives

  • Add the missing comma between the arguments.
  • Add the missing operator to build a full expression. There may be many ways to make the expression valid.
  • Close the function call with a closing parenthesis, and start a new expression after it.

syntax error, unexpected identifier “%s”, expecting “,” or “;”

Description

This error is not related to the upcoming identifier, but to the previous delimiters. In both cases of the illustration, a string was started, with single or double quotes: yet, inside these strings, there was another set of the same delimiter. The parser could not differentiate between the two usages, and exited the string.

Example

<?php

// missing a '
echo '<a href='https://www.exakat.io'>Exakat.io</a>';

// missing a " 
echo "<a href="https://www.exakat.io">Exakat.io</a>";

// missing as between identifier
use OpenApi\Attributesas OA;

?>

Alternatives

  • Escape quotes inside a string, when they are used as delimiter.
  • Use the other quotes inside the string: if single quotes are used as delimiters, use double quotes in it.
  • Switch to the heredoc syntax, to simplify the syntax for both quotes.
  • Add the missing as, between the two identifiers, in a use instruction.

syntax error, unexpected identifier “%s”, expecting “;” or “{”

Description

An abstract method’s signature must be terminated with a semicolon, since it has no body, and a concrete method’s signature must be followed by a { opening the body. Here, an extra identifier was found right after the closing parenthesis of the argument list, where PHP expected one of those two terminators.

This typically happens when a return type declaration is missing its leading colon, or when a stray word was left over after editing the signature.

Example

<?php

abstract class X {
    abstract function foo() bar;
}

?>

Literal Examples

  • syntax error, unexpected identifier “bar”, expecting “;” or “{”

Alternatives

  • If a return type was intended, add a colon before it: abstract function foo(): bar;.
  • Remove the extra identifier.
  • If the method should have a body, replace the identifier with { and the method’s code.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected identifier “%s”, expecting “]”

Description

PHP has found two identifiers, one next to the other. This might happen inside an attribute declaration or a function call, where a separator has been forgotten.

Example

<?php

#[A name:a)]  // forgotten opening parenthesis
class X {}

?>

Alternatives

  • Close the attribute with a closing square bracket. The following code needs to be updated too.
  • Open the argument part of the attribute, with an opening parenthesis.

syntax error, unexpected identifier “%s”, expecting “function” or “const”

Description

PHP identified a name in the body of a class, although it was not preceded by a keyword.

The error may suggest function, but any definition keyword will do: private, protected, public, var, const, function, use.

Example

<?php

class X {
    publicfunction foo() {}
}

?>

Literal Examples

  • syntax error, unexpected identifier “publicfunction”, expecting “function” or “const”

Alternatives

  • Add a definition keyword before the name.
  • Fix the syntax and make a keyword appear at the beginning of the definition.

In more recent PHP versions, this error message is now :ref:syntax-error,-unexpected-identifier-"%s",-expecting-"function".

syntax error, unexpected identifier “%s”, expecting “function”

Description

PHP identified a name in the body of a class, although it was not preceded by a keyword.

The error may suggest function, but any definition keyword will do: private, protected, public, var, const, function, use.

Example

<?php

class X {
    publicfunction foo() {}
}

?>

Literal Examples

  • syntax error, unexpected identifier “publicfunction”, expecting “function”

Alternatives

  • Add a definition keyword before the name.
  • Fix the syntax and make a keyword appear at the beginning of the definition.

In previous PHP versions, this error message used to be :ref:syntax-error,-unexpected-identifier-"%s",-expecting-"function"-or-"const".

syntax error, unexpected identifier “%s”, expecting “{”

Description

In this case, PHP found two identifiers in a row: X and Y. This never happens in PHP code. Either a keyword should have separated them, or one of them is a duplicate.

Example

<?php

class X Y {}

enum E Z {}

interface I W {}

?>

Alternatives

  • Add a missing keyword between the two identifiers: here, implements or extends could work.
  • Remove one of the duplicate name.

syntax error, unexpected identifier “%s”, expecting variable or “$”

Description

new works with objects, static properties and normal properties. It does not work with class constants, even if the constant is an object.

Example

<?php

class A  {
    const B = C;
}

const C = new A;

var_dump(new A::B);

?>

Literal Examples

  • syntax error, unexpected identifier “B”, expecting variable or “$”

Alternatives

  • Store the constant in a variable, and new the variable.
  • Get the class name with get_class or ::class and then, create the new object.

syntax error, unexpected identifier “%s”, expecting variable

Description

A foreach() structure requires a variable after the as keyword: in fact, it may be a variable, a property, a static property, an array index or the list() expression.

The same error also appears when the intersectional type syntax is used: While A& is valid PHP 8.0, it should be followed by a variable (a parameter), and it finds another type.

Example

<?php

foreach($a as b) {}

function foo(A&B $arg) {}

?>

Literal Examples

  • syntax error, unexpected identifier “B”, expecting variable
  • syntax error, unexpected identifier “b”, expecting variable
  • syntax error, unexpected identifier “Countable”, expecting variable

Alternatives

  • Add the missing $ sign, to make the identifier an array.
  • Upgrade to PHP 8.2, with intersectional types.
  • Remove the intersectional types.

syntax error, unexpected identifier “%s”

Description

This error appears when two identifiers are following each other. This is usually rooted in a missing keyword or character.

Named structures usually start with a keyword, such as class, interface, function, etc.

In a function call, a missing opening parenthesis brings the named parameter and the function name together.

The error also appears when new lines are used inside a namespace. This was valid until PHP 8.0, but is not anymore.

Example

<?php

// missing keyword: class, or interface
A extends B {}

// missing opening parenthesis
foo name:1);

// new lines in namespace
echo \A
      B\ 
      C;

?>

Literal Examples

  • syntax error, unexpected identifier “A”

Alternatives

  • Add the missing keyword before the identifier.
  • Add a missing opening parenthesis to the function call.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See MultilineQualifiedName

syntax error, unexpected identifier “readonly”, expecting “function” or “const”

Description

This syntax error signals that readonly is still considered as an identifier, and not as a keyword. This happens when the underlying PHP version is too old for the source code.

Example

<?php

class X {
    readonly int $property;
}

?>

Alternatives

  • Remove the readonly option.
  • Upgrade to PHP 8.1 or more recent.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected integer “%s”, expecting “)”

Description

This error is a variation of the named parameter typo: the missing semi colon between the name and the value leads to an identifier next to an unrelated operator. The suggestion to use a closing parenthesis is valid, though not the only one.

Example

<?php

foo(arg new B());

class B {}

function foo(B $arg) {}

?>

Alternatives

  • Add the missing : before the integer.
  • Add the missing ) before the integer, and may be a comma, depending on the context.

syntax error, unexpected namespaced name “%s”, expecting “function”

Description

A namespaced name is an identifier with at least one backslash. The body of a class, enumeration, trait or interface does not use any namespaces, as it declares methods, constants and proeprties. There may be namespaced names in a use declaration, but such expression starts with a keyword.

Example

<?php

class X {

A\B;

C\D($e);

}

?>

Literal Examples

  • syntax error, unexpected namespaced name “A\B”, expecting “function\

Alternatives

  • Add the use keyword before the name to import a trait.
  • Add the function keyword before the name to make it a method, although there should not be any \ in the method name.
  • Add the const keyword before the name to make it a constant, although there should not be any \ in the constant name.
  • Add the #[ keyword before the name to make it an attribute.

syntax error, unexpected single quoted string “%s”, expecting “)”

Description

After an identifier, such as name, there can only be a delimiter, such as (, [, or : but not a string.

Example

<?php

foo(name 'A');

?>

Literal Examples

  • syntax-error,-unexpected-single-quoted-string-“A”,-expecting-“)”

Alternatives

  • Add a colon between name and 'A', to make a named parameter.
  • Add parenthesis after name and around 'A', to make a function call.
  • Add square brackets after name and around 'A', to make a array call.

syntax error, unexpected string content

Description

This error appears when a single quote string is not properly closed. In the example, there is an opening single quote, but not a closing one. PHP tries to use the rest of the code as a literal string, and ends up without tokens to wrap up the code legally.

Example

<?php

{ $a = '1+2; }

Alternatives

  • Close the string with a single quote.
  • Close the string with a double quote.

syntax error, unexpected token “#[”, expecting “)”

Description

Attributes can only be placed in front of the declarations that support them, such as classes, functions, methods and parameters. A catch block’s caught-exception clause does not accept an attribute: PHP was expecting the closing parenthesis of the catch (...) clause, and found the beginning of an attribute, #[, instead.

Example

<?php

try {
} catch (Exception #[SomeAttribute] $e) {
}

?>

Alternatives

  • Remove the attribute from the catch clause.
  • Move the attribute to a declaration that supports it, such as the enclosing method.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “#[”, expecting “,” or “;”

Description

The #[ token marks the beginning of an attribute. The previous statement is either not finished with a semi-colon, or could be extended with another set of code and then finished with a semi-colon.

Example

<?php

// missing ; or , 
use A as B

#[MyAttribute]
class X {}

?>

Alternatives

  • Finish the previous use statement, with a semi-colon.
  • Complete the previous use statement, and finish it with a semi-colon.

syntax error, unexpected token “#[”, expecting “]”

Description

It is not possible to nest attributes, so the first attribute must be finished, with a closing square bracket, before opening the second one.

Example

<?php

#[A
#[B]
class X {}

?>

Alternatives

  • Close the first attribute with a closing square bracket.
  • Remove the extra opening #[ attribute, and use a comma.

syntax error, unexpected token “%”

Description

PHP accepts one percentage %, for modulo. The % operator requires 2 operands, one before, and one after. This is not the same as + and -, which can be used as unary operator.

Example

<?php

$a = 2 + % 3;

?>

Alternatives

  • Remove the superfluous percentage.

syntax error, unexpected token “%s”, expecting identifier

Description

This error arises when a PHP token is used where a name is expected. There is a conflict between the PHP token, which has its own meaning, and the expected name, which is a ‘T_STRING’ token.

This happens with any named structure, such as CITE, functions and global constants. It is legit with class constants and methods.

The identifier can be any string, that satisfy the regex ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$, and is not a PHP keyword.

This error is case insensitive, like PHP keywords.

Example

<?php

class Match {} 
trait Switch {} 

class echo {} 
interface ECHO {} 
enum echo {} 
trait echo {} 
function echo() {} 
const echo = 1;

?>

Alternatives

  • Add a distinguishing prefix or suffix to the name to stay out of conflict with PHP keywords.
  • Check if the PHP version introduces new keywords.
  • Make the function a method.
  • Make the constant a global constant.
  • Prefix or suffix the name, to make it a normal word, not a keyword.

syntax error, unexpected token “&”, expecting end of file

Description

& is the reference operator. It returns a reference to a value, and cannot be used standalone, or on the left part of an assignation.

Example

<?php

&$x;

&E_ALL;

$c = &'33';

?>

Alternatives

  • Remove the whole expression.
  • Put this expression in another variable, with an assignation.
  • Put this expression in another variable, and make the reference on that variable.

syntax error, unexpected token “&”

Description

The & operator is used in two distinct situations: as the bitwise operator, between two different values; as the reference operator, before a variable.

As the reference operator, it may be used in a method signature, to identify a passed-by-reference argument. It may not be used anymore at call time, for sending an argument nor receiving a value.

The reference operator returns a new reference, and it should be stored in another variable (or any data container). Otherwise, it is.

Example

<?php

function foo(&$a) {}

// Cannot make a reference at call time
foo(&$c);

// Cannot return a reference at call time
$d = &foo($c);

?>

Alternatives

  • Remove the & in function call’s argument, and put it in the function signature.
  • Remove the & in function call returned value, and put it in the function signature.

syntax error, unexpected token “(”, expecting “::”

Description

This error appears when calling static as a function. static cannot be used as a function name. It may be used as class name, in a new expression, or as an method. It is often used in a static call, for methods, constant or properties.

It is not recommended to use static as a method name.

Example

<?php

static();

?>

Alternatives

  • Add the object before the method name.
  • Add the class name and :: before the method name.
  • Add the new operator before the static keyword. Make sure that code is within a class or assimilated.

syntax error, unexpected token “(”, expecting identifier or variable or “{” or “$”

Description

The object operators -> and ?-> both expect a name as second operand, aka on the right. Here, the name of the method was forgotten and the operator tried to use ( as a name, which is not allowed.

Example

<?php

// missing a method name
$object-> ();

// missing a method name
$object?-> (1);

?>

Alternatives

  • Add a name after the -> and ?->, such as $object->method.
  • Add a name inside a variable after the -> and ?->, such as $object->$methodName.
  • Add a name inside an expression after the -> and ?->, such as $object->{$variable . 'suffix'}().
  • Add a name inside an variable variable after the -> and ?->, such as $object->$$variable().

syntax error, unexpected token “(”, expecting variable

Description

PHP started recognizing a property definition, with its visibility, a type and now expects a variable name. In fact, the function keyword was omitted.

Example

<?php

class X {
    public  __construct () {}
}

?>

Alternatives

  • Add the function keyword, before the name of the method.
  • Remove the parenthesis and the following tokens, and make a proper property definition.

syntax error, unexpected token “(”

Description

Parenthesis cannot be placed anywhere, although they have a wide range of applications. In particular, they are used to call methods, by delimiting arguments; and set part of expressions apart.

A class cannot hold a closure, only method, which are functions with a name.

The syntax to call a method on an instantiation new x()->foo() and new x()() has been introduced in PHP 8.4.

Example

<?php

// methods cannot be closure. They need a name
class X {
    function () {}
}

// This is a PHP 8.4 syntax, cannot be used before.
new $x()(); 
// equivalent to (new $x())->__invoke();

?>

Alternatives

  • Add the name to the method.

syntax error, unexpected token “(int)”

Description

This is a bug in the parser engine of PHP: (int), (array) or the other cast operators, are recognized early in the code parsing, and are also confused inside a function call.

Example

<?php

var_dump(int);

?>

Alternatives

  • Do not use any global constant, with the name of a cast operator: int, float, unset, etc.

syntax error, unexpected token “)”, expecting “=”

Description

In this case, the = is missing, and the 1 has been merged into the strict_types to become an identifier. PHP expects a = after this identifier.

Example

<?php

declare(strict_types1);

?>

Alternatives

  • Add = after strict_types.

syntax error, unexpected token “)”, expecting “function” or “fn” or “static” or “#[”

Description

In this command, an attribute has been configured. The attributes can only precede a structure, such as a class, method or function.

In this case, the attribute has been placed inside an function call, so only a closure can be declared.

This error appears after PHP 8.0: this is when the #[ token was introduced. Until that version, # introduces a comment, until the end of the line.

Example

<?php

foo(#[a]);

function foo(Closure $f) {}

?>

Alternatives

  • Finish declaring a closure, with fn or function in the argument.
  • Remove the attribute.
  • Turn the attribute into a comment.
  • [syntax-error,-unexpected-token-“;”,-expecting-“function”-or-“fn”-or-“static”-or-“#“

syntax error, unexpected token “)”, expecting variable

Description

An attribute placed inside a parameter list must be immediately followed by the parameter it decorates. Here, the attribute is the last thing before the closing parenthesis, so PHP expects a variable to declare the parameter, but finds the closing parenthesis instead.

Example

<?php

function foo(string $a, #[SomeAttribute]) {}

?>

Alternatives

  • Add the missing parameter, with its $ variable, right after the attribute.
  • Remove the trailing attribute if no extra parameter was intended.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “)”

Description

This error appeas when the parenthesis is needed, but not at that place.

In the illustration, the parenthesis should be not be used directly after a multiplication sign: that operator needs a second operand.

Example

<?php

$a = (3 * 3 * );

?>

Alternatives

  • Add the missing operand to the previous operator.

syntax error, unexpected token “*”

Description

PHP accepts one star *, for multiplication and two stars **, for power, since PHP 7.0. More stars are not supported as operator.

Example

<?php

// star cannot be used directly after a +
$a = 2 + * 3;

// No such operator as 3 stars
$a = 2 *** 3;

?>

Alternatives

  • Remove the previous operator, before the star.
  • Finish the previous operation, before the star.
  • Remove the superfluous star.

syntax error, unexpected token “,”, expecting “)”

Description

The new call was not properly closed with a closing parenthesis, and PHP found a closing square bracket, instead.

Example

<?php

#[A(new X( a: 'b',    ]
class X {}
    
?>

Alternatives

  • Add a closing parenthesis after the comma.
  • Remove the comma, and add a closing parenthesis.

syntax error, unexpected token “,”, expecting “]”

Description

A comma was found in an array syntax: the syntax is $variable[$index], and there can be only one index between the brackets.

Example

<?php

echo $a[1,2];

?>

Alternatives

  • Remove the comma and the code after it, until the closing bracket.
  • Close the square bracket, open a new one and remove the comma: $a[1][2].

syntax error, unexpected token “,”, expecting variable or “$”

Description

This error is reported when a list of global variable is expected after the global keyword.

There is a similar case with the visibility options public, protected and private, and the static keyword, although global is the only keyword with accepts variable variables.

Generally speaking, there can be no two successive commas in an expression, except with the list() keyword.

Example

<?php

class X {
	public function foo() {
	    global $a, , $c;
	}
}

?>

Alternatives

  • Remove the extra comma.
  • Fill the empty slot with a variable.

syntax error, unexpected token “,”, expecting variable

Description

This error is reported when a list of variable is expected after a keyword.

This is the case with the visibility options public, protected and private, which expect a list of property names.

This is also the case with global and static, which are declaring global and static variables.

Generally speaking, there can be no two successive commas in an expression, except with the list() keyword.

Example

<?php

class X {
	public $a, , $c;
	
	public function foo() {
	    static $a, , $c;
	}
}
?>

Alternatives

  • Remove the extra comma.
  • Fill the empty slot with a variable.

syntax error, unexpected token “,”

Description

A comma is used to separate arguments in a function call. A functioncall may also use named parameters, to identify the arguments. In this case, the name of the parameter is provided, but not its value.

Example

<?php

    #[Attribute(name: , value: 1)]
    class X {}

?>

Alternatives

  • Remove the parameter name from the function call.
  • Provide a value for the parameter name in the functioncall.

syntax error, unexpected token “\”, expecting “{”

Description

This syntax error is related to the usage of PHP keyword in a namespace. Until PHP 8.0, the namespace could not use any such keyword, and produced a compilation error.

Example

<?php

namespace A\eval\B;

?>

Alternatives

  • Upgrade to PHP 8.0 or more recent.
  • Rename the namespace to avoid using PHP keywords.

syntax error, unexpected token “->”, expecting “,” or “;”

Description

The object operator -> is used in an expression, where it is not expected.

Here, it is a global variable statement. Such statement were possible in PHP 5 and older, but are not valid anymore since PHP 7.0. Then, PHP would use the content of the property as the name of the global variable.

The same error is emitted with static variables, with the :: and the ?-> operators.

Example

<?php

global $object->property;

static $object->property;

?>

Alternatives

  • Remove the property or method call from the global instruction.

syntax error, unexpected token “->”

Description

This error reports that the object syntax was not expected there.

One classic reason is the new syntax in PHP 8.4, where parenthesis are not necessary, right after a new, to call properties or methods. This syntax actually requires the parenthesis.

Another situation arise when a space is inserted between the ? and the -> operator. The space let PHP believe that a ternary operator is started, yet the -> must be applied to an object.

Example

<?php

// should be new X()->method();
new X->method();

// wrongly build null object operator
echo $obj ?
    -> foo;

?>

Alternatives

  • Add the parenthesis on the new call.
  • Write the ?-> without spaces.

syntax error, unexpected token “:”, expecting “)”

Description

Single colons : are allowed in a method call, as they separate the value and the name of the named parameter. Here, the name of the parameter is missing.

Example

<?php

foo(a:1, : 2);

?>

Alternatives

  • Add the name of the parameter before the colon.
  • Remove the colon.

syntax error, unexpected token “:”, expecting “]”

Description

Colons are used with the ternary operators, labels and named parameters. They may also be involved in a typo with a double colon, that lost one half of its elements.

Example

<?php

#[A\Bc: 'D')]

?>

Alternatives

  • Add the missing parenthesis between the B attribute name and the c named parameter.

syntax error, unexpected token “:”

Description

A syntax error is a generic error, where PHP could not compile the code. Here are some classic typo or seemingly valid code that leads to this error.

  • Since PHP 8.0, named parameters may be used, though parameters don’t use the initial $ sign.

Example

<?php

// calling a named parameter, with the $ in the parameter name
foo($c: 1);

?>

Alternatives

  • Fix the name of the parameter.

syntax error, unexpected token “::”, expecting “,” or “;”

Description

The object operator :: is used in an expression, where it is not expected.

Here, it is a global variable statement. Such statement were possible in PHP 5 and older, but are not valid anymore since PHP 7.0. Then, PHP would use the content of the property as the name of the global variable.

The same error is emitted with static variables, with the :: and the -> operators.

Example

<?php

global $object::$property;

static $object::$property;

?>

Alternatives

  • Remove the property or method call from the global instruction.

syntax error, unexpected token “::”, expecting “:”

Description

In this example, Match is a PHP keyword, and cannot be part of a static call, with the operator ::. On the other hand, Match could be a parameter name, where the foo function, has a $Match parameter. Hence, the suggestion to use : a single colon.

This error may also appear with other keywords, such as Switch. It is also case-insensitive.

Example

<?php

foo(Match::a());

?>

Alternatives

  • Use a single colon, if $Match is actually a parameter name.
  • Rename the Match class to avoid conflicts with PHP keywords.

syntax error, unexpected token “::”, expecting “]”

Description

Inside the square brackets of an array index, PHP expects an expression identifying the key, followed by the closing ]. The scope resolution operator :: cannot start an expression on its own: it must be preceded by a class name, a variable or one of self, parent or static. Here, PHP found :: immediately, so it reports that it was still expecting ] to close the array access.

The same message also appears whenever a previous [ was left unclosed, and a later, unrelated :: is the first token that cannot continue the pending index expression.

Example

<?php

    $arr = [1, 2, 3];
    $y = $arr[::];

?>

Alternatives

  • Provide the missing class name (or self, parent, static) before ::, such as $arr[X::CONST].
  • Check that every previous [ in the file has a matching ].
  • [syntax-error,-unexpected-token-“public”,-expecting-“]”](syntax-error,-unexpected-token-public,-expecting-].html)
  • [syntax-error,-unexpected-token-“class”,-expecting-“]”](syntax-error,-unexpected-token-class,-expecting-].html)
  • [syntax-error,-unexpected-token-“if”,-expecting-“]”](syntax-error,-unexpected-token-if,-expecting-].html)

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “::”

Description

In this situation, the keyword or is reserved by PHP and cannot be used as a class name, a function name, or a global constant.

By extension, the or keyword cannot be used in static object notations, such as calling a constant, or a static method or property.

This error may arise with other keywords, such as switch, and, foreach, etc, for similar reasons. It also may happen when a new keyword is reserved by PHP, between two versions.

The error also appears when the left operand of the :: is missing, or not applicable. Here, there is an illustration with echo.

Example

<?php

// double-colon on an operator
1 or::A;

echo ::class;

// double-colon on a number
1::class;

?>

Alternatives

  • Rename the class with a PHP non-keyword.

syntax error, unexpected token “;”, expecting “(”

Description

This syntax error is related to a new PHP feature. In PHP 8.3, a new syntax for dynamic access to class constants was introduced. It was not supported until then.

Example

<?php

class A {
	public const A = 1;
}

$b = 'A';

echo A::{$b};

?>

Alternatives

  • Upgrade PHP to PHP 8.3 or more recent.
  • Use a call to constant() to reach the value of the class constant.

syntax error, unexpected token “;”, expecting “)”

Description

A semi-colon was found after an opening parenthesis. To keep the code balanced, PHP expects the parenthesis to be closed before finishing the instruction.

Example

<?php

array(1,2; );

foo(3,4;);

function foo($a = 3;) {}
?>

Alternatives

  • Remove the semi-colon.
  • Close the parenthesis before the semi-colon.

syntax error, unexpected token “;”, expecting “,” or “)”

Description

The declare instruction was not finished properly. declare accepts one or more parameter. With one parameter, the instruction must be closed with a closing parenthesis after the value expression; with multiple parameters, the parameters are separated by commas ,, and the last parameter is followed by a closing parenthesis.

This error message is dedicated to declare, as similar other syntaxes yield distinct error messages.

Example

<?php

declare(strict_types=1;

?>

Alternatives

  • Add a closing parenthesis between the 1 and the semi-colon ;.
  • Add a comma after the 1, provide another parameter, and close the declare with a closing parenthesis.

syntax error, unexpected token “;”, expecting “->” or “?->” or “[”

Description

The & reference operator turns a value into a reference. It works with data containers, such as variables, properties or array elements. It doesn’t work on literal constants.

The error message suggestion to use extra operators such as [ or -> leads to a distinct error: Cannot use temporary expression in write context.

This error is also raised with a reference on a new operator. The problem is on the reference operator, but the parser tries to understand more details later in the code before coming back to it.

Example

<?php

$a = &E_ALL;

const B = [1,2,3];
//Cannot use temporary expression in write context
$c = &B[2]; 

// The error is actually on the &
$x = & new X();

?>

Alternatives

  • Store the constant in a variable, and make the reference on the variable.
  • Use constants by value, not by reference.
  • Remove the reference operator & before the new call.

In previous PHP versions, this error message used to be :ref:syntax-error,-unexpected-token-";",-expecting-"->"-or-"?->"-or-"{"-or-"[".

syntax error, unexpected token “;”, expecting “->” or “?->” or “{” or “[”

Description

The & reference operator turns a value into a reference. It works with data containers, such as variables, properties or array elements. It doesn’t work on literal constants.

The error message suggestion to use extra operators such as [ or -> leads to a distinct error: Cannot use temporary expression in write context. The suggestion to use { is the then-deprecated curly brace syntax for array access. It is still valid in PHP 8.3, but removed in PHP 8.4.

Example

<?php

$a = &E_ALL;

const B = [1,2,3];
//Cannot use temporary expression in write context
$c = &B[2]; 

?>

Alternatives

  • Store the constant in a variable, and make the reference on the variable.
  • Use constants by value, not by reference.

In previous PHP versions, this error message used to be :ref:syntax-error,-unexpected-';',-expecting-'['. In more recent PHP versions, this error message is now :ref:syntax-error,-unexpected-token-";",-expecting-"->"-or-"?->"-or-"[".

syntax error, unexpected token “;”, expecting “]”

Description

A semi-colon was found after an opening square bracket. To keep the code balanced, PHP expects the bracket to be closed before finishing the instruction.

Example

<?php

[1,2; ];

$a[4;];

?>

Alternatives

  • Remove the semi-colon.
  • Close the square bracket before the semi-colon.

syntax error, unexpected token “;”, expecting “function” or “fn” or “static” or “#[”

Description

In this command, an attribute has been configured. The attributes can only precede a structure, such as a class, method or function.

In this case, the attribute has been placed inside an expression, so only a closure can be declared: hence, the request for a function, fn. That closure could be static or have another attribute.

In the end, the closure is not compatible with the + or similar operator, so the suggestion is not valid here. It could be valid with a comma.

This error appears after PHP 8.0: this is when the #[ token was introduced. Until that version, # introduces a comment, until the end of the line.

Example

<?php

1 + #[attribute];

Alternatives

  • Remove the attribute.
  • Turn the # comment into a // comment.
  • [syntax-error,-unexpected-token-“)”,-expecting-“function”-or-“fn”-or-“static”-or-“#“

syntax error, unexpected token “;”, expecting “{”

Description

Namespace accepts two syntaxes: the first one with an ending semi-colon, or a block, which starts with an opening curly bracket.

In the current case, there is another feature at play: the name of the namespace may be empty, to refer to the global namespace. In that case, either the namespace keyword is omitted, or a block is defined after the namespace.

Example

<?php

namespace ;
?>

Alternatives

  • Remove the namespace ; entirely.
  • Add a block after the namespace, and remove the semi-colon.

syntax error, unexpected token “;”, expecting identifier

Description

The use instruction is not finished properly: as expects a name after it.

Example

<?php

use A\B as ;

?>

Alternatives

  • Finish the use + as with an alias name.
  • Remove the as to make a simple use instruction.

syntax error, unexpected token “;”

Description

The semi-colon marks the end of a command. They are needed in blocks, or sequences of commands.

In the first case, the semi-colon signals the end of the exit command, and PHP is still parsing the if condition.

In the second case, the semi-colon is understated by the closing PHP tag. The previous attribute #[A] requires a structure (class, interface, function…), which is not found.

Example

<?php

// 'if' needs a second closing ), but PHP keeps parsing it until the semi colon.
if ($d !== foo() {
    exit(1);
}

#[A()] 
// This is an attribute, and it needs a structure to apply to. 

?>

Alternatives

  • Check previous opening and closing parenthesis, they might be unbalanced.

syntax error, unexpected token “<<”

Description

This error might be related to the left bitshift operator, although it is often related to a git diff leftover. Here, a merge conflict was left in the code, and the first and erroneous characters are <<.

There are other possibilities of error with that operator, although they are less common.

Example

<?php

<<<<<<< HEAD
    $a = 2 * $b;
=======
    $a = 3 * $b + 1;
>>>>>>> e0ce25cd1fe156c2f50def834532e489b923dcef

?>

Alternatives

  • Remove the diff from the code, as it doesn’t compile.
  • Fix the merge conflict.

syntax error, unexpected token “=”, expecting identifier or variable or “{” or “$”

Description

The object operators -> and ?-> both expect a name as second operand, aka on the right. Here, the name was forgotten and the operator tried to use = as a name, which is not allowed.

Example

<?php

// missing a property
$object-> = 3;

// missing a property
$object?-> = 3;

?>

Alternatives

  • Add a name after the -> and ?->, such as $object->property.
  • Add a name inside a variable after the -> and ?->, such as $object->$name.
  • Add a name inside an expression after the -> and ?->, such as $object->{$variable . 'suffix'}.
  • Add a name inside an variable variable after the -> and ?->, such as $object->$$variable.

syntax error, unexpected token “=”, expecting identifier

Description

In this error, the declared optin name value has been removed. It could be strict_types, ticks or encoding.

Example

<?php

declare(= 1);

declare(= 'iso-8859-1');

?>

Alternatives

  • Add strict_types before the = operator.
  • Add ticks before the = operator.
  • Add encoding before the = operator.
  • Remove the declare call.

syntax error, unexpected token “=”, expecting variable

Description

The name of the parameter was removed. The parameter name has the syntax of a variable, hence the expected variable mentioned in the error.

Example

<?php

function foo( = 0) {}
?>

Alternatives

  • Add the argument name.
  • Remove the parameter entirely.

syntax error, unexpected token “=”

Description

The = assignation operator is found after a constant name. Constants are defined with const keyword, and later, they are not changed.

Example

<?php

a = 1;

?>

Alternatives

  • Turn the constant name into a variable name by adding a $ sign before it.
  • Make this code a constant definition by adding const before it, if it was not already defined.

syntax error, unexpected token “>”

Description

This syntax error is characteristic of the pipe operator |> being used in version older than PHP 8.5.

Example

<?php

'abc' |> strtoupper(...);

?>

Alternatives

  • Upgrade to PHP 8.5.
  • Nest the calls, instead of using the pipe operator.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “?”, expecting identifier

Description

This error happens when trying to add a type to a global constant. Only class constants can be typed, since PHP 8.3; a top-level const declaration never supports a type, so the parser expects the constant’s identifier right after the const keyword and rejects the ? (or any other type token) that appears instead.

Example

<?php

const ?int GLOBAL_TYPED = true;

?>

Alternatives

  • Make the constant a class constant, which can be typed since PHP 8.3.
  • Remove the type from the constant definition.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “?”

Description

? is used in several syntaxes in PHP.

  • as null in a type specification (argument, returntype, property, class constant), when it is the first type specified: ?A $a
  • as the terny operator $condition ? $then : $else. Then, the condition must be a complete expression.

Example

<?php

// an unfinished ternary operation
$a = 1 + ? 3 : 2 ;

// ? should be written null in a type specification
function foo(a|? $a) {}

?>

Alternatives

  • Finish the expression before the ? in a ternary operation.
  • Use the null type when specifying a type.

syntax error, unexpected token “?->”, expecting “,” or “;”

Description

The object operator ?-> is used in an expression, where it is not expected.

Here, it is a global variable statement. Such statement were possible in PHP 5 and older, but are not valid anymore since PHP 7.0. Then, PHP would use the content of the property as the name of the global variable.

The same error is emitted with static variables, with the :: and the -> operators.

Example

<?php

global $object->property;

static $object->property;

?>

Alternatives

  • Remove the property or method call from the global instruction.

syntax error, unexpected token “?->”

Description

This error reports that the object syntax was not expected there.

One classic reason is the new syntax in PHP 8.4, where parenthesis are not necessary, right after a new, to call properties or methods. This syntax actually requires the parenthesis.

Example

<?php

// should be new X()?->method();
new X?->method();

?>

Alternatives

  • Add the parenthesis on the new call.

syntax error, unexpected token “??”

Description

?? is used as the coalesce operator.

The expression on the left side of that operator must be completed of it to be valid.

Example

<?php

// an unfinished coalesce operation
$a = 1 + ?? 3;

?>

Alternatives

  • Finish the expression before the ? in a ternary operation.

syntax error, unexpected token “]”

Description

This error appeas when the closing bracket is needed, but not at that place.

In the illustration, the closing square bracket should be not be used directly after a multiplication sign: that operator needs a second operand.

Example

<?php

$a = [3 * 3 * ];

?>

Alternatives

  • Add the missing operand to the previous operator.

syntax error, unexpected token “NAMESPACE”, expecting “(”

Description

It is not possible to use __NAMESPACE__ or any other magic constant as a function or method name. This error is case insensitive.

Example

<?php

function __NAMESPACE__() {}

?>

Literal Examples

  • syntax-error

Alternatives

  • Use another name than __NAMESPACE__.

syntax error, unexpected token “as”

Description

The as token was found, where it was not expected. as is often used as a modulator of another instruction: foreach, use, function.

Example

<?php

A\B as C;

?>

Alternatives

  • Add a missing use to start the instruction.

syntax error, unexpected token “break”

Description

break is a token that stop the current loop or switch, and proceed from the end of that loop. break is standalone expression, and cannot be part of another expression: this is why it is forbidden in the array, or the match command.

Example

<?php
    // break does not fit everwhere
    $a = [1 => break ];

    // break is for switch, not match
    $b = match($c) {
        1 => break,
    };

?>

Alternatives

  • Remove the break, and find another way to jump out of the loop.

syntax error, unexpected token “class”, expecting-“]”

Description

The previous attribute was not closed with a square bracket, and its syntax is spilling over the supporting class.

Example

<?php

#[Attribute()
class X {}

?>

Alternatives

  • Remove the attribute.
  • Close the attribute with a square bracket.
  • [syntax-error,-unexpected-token-“::”,-expecting-“]”](syntax-error,-unexpected-token-::,-expecting-].html)
  • [syntax-error,-unexpected-token-“public”,-expecting-“]”](syntax-error,-unexpected-token-public,-expecting-].html)

syntax error, unexpected token “const”

Description

There are several reasons why a const token is found misplaced.

Attributes on global constants are supported since PHP 8.5. Before that version, they are not recognized, and yield this syntax error.

The error also appears when the const keyword is used in the body of the code, outside the main code: this means in any control flow block, such as ifthen, switch, etc. and in any structure like function, method, etc. It is still OK to use const in the body of a class, interface, trait or enum. In such cases, one must use define() to define a constant.

Example

<?php

#[ConstAttribute]
const A = 1;

if ($condition) {
    // global constant must be in the global space, and cannot be conditional
    const X = 2;
}

class X {
    function foo() {
        // global constant must be in the global space, and cannot be conditional
        const Y = 2;
    }
}

?>

Alternatives

  • Remove the attribute.
  • Refactor the global constant to a class constant.
  • Use define() instead of const.
  • Use the ternary operator ? : inside the constant definition.
  • Use inclusion.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “continue”

Description

continue is a token that stop the current loop or switch, and proceed from the end of that loop. continue is standalone expression, and cannot be part of another expression: this is why it is forbidden in the array, or the match command.

Example

<?php
    // break does not fit everwhere
    $a = [1 => continue ];

    // break is for switch, not match
    $b = match($c) {
        1 => continue,
    };

?>

Alternatives

  • Remove the continue, and find another way to jump out of the loop.

syntax error, unexpected token “exit”

Description

This error reports a badly placed exit or die command. Both of them are represented with the same exit token, hence the naming of the error.

Example

<?php

$a = 1
die();

?>

Alternatives

  • Make sure the previous instruction is complete, with its semi-colon.

syntax error, unexpected token “extends”, expecting “{”

Description

When declaring a class, the extends keyword must appear before the implements one. There is only one (or no) class extension, so the extends list is often shorter than the implements list.

Example

<?php

class X implements I1, I2 extends W {}

?>

Alternatives

  • Move the extends keyword, and its class, right after the name of the class, and before the implements keyword.
  • Remove the extends keyword.

syntax error, unexpected token “extends”, expecting identifier

Description

The extends keyword may only be used after a class name, an interface name, or the parenthesis of an anonymous class.

Example

<?php

// this is missing the name of the class 
class  extends B {}

// this is missing the name of the interface
interface  extends B {}

?>

Alternatives

  • Add a name to the class.
  • Add a name to the interface.
  • Add set of parenthesis to the class to make it anonymous.

syntax error, unexpected token “extends”

Description

extends is a PHP token, which appears inside a class or interface structure. It cannot be find anywhere else.

Example

<?php

X extends Y { }

enum Y extends Z { }

?>

Alternatives

  • Check that a class or an interface have been started.

syntax error, unexpected token “final”, expecting “(”

Description

final is not a valid name for a function. It is a valid name for a method, though.

Example

<?php

function final() {};

?>

Alternatives

  • Use another name for that function.
  • Remove the name, and create a closure instead.

syntax error, unexpected token “if”, expecting “)”

Description

If-then commands are standalone commands. They can’t be part of another expression. Here, PHP found the if, while it was expecting another expression.

Then, PHP mentions that it was expecting ): this usually hints at an unclosed method call syntax. In the example here, the previous line holds an unclosed function call to foo.

Example

<?php

$a = foo(1 

if ($a == 2) {
    print OK;
}

?>

Alternatives

  • Look for the previous opening ( parenthesis in functioncalls and check that it is balanced.
  • Look for all previous openings ( parenthesis in functioncalls and check that they are all balanced.

syntax error, unexpected token “if”, expecting “]”

Description

If-then commands are standalone commands. They can’t be part of another expression. Here, PHP found the if, while it was expecting another expression.

Then, PHP mentions that it was expecting ]: this usually hints at an unclosed array syntax. In the example here, the previous line holds an unclosed array.

Example

<?php

$a = [1,2, 

if ($a == 2) {
    print OK;
}

?>

Alternatives

  • Look for the previous opening [ square bracket and check that it is all balanced.
  • Look for all previous openings [ square brackets and check that they are all balanced.
  • [syntax-error,-unexpected-token-“::”,-expecting-“]”](syntax-error,-unexpected-token-::,-expecting-].html)
  • [syntax-error,-unexpected-token-“public”,-expecting-“]”](syntax-error,-unexpected-token-public,-expecting-].html)

syntax error, unexpected token “if”

Description

If-then expressions are standalone expressions, and cannot be used inside another expression. Hence, they must be preceded by a semi-colon, or any other expression closing character.

Example

<?php

$a = foo() && if ($a == 2) { echo $a; } else { echo "No A"; }

match( 
if ($a == 2) { echo $a; } else { echo "No A"; }

?>

Alternatives

  • Replace the && by a semi-colon.
  • Move the $a = foo() && inside the if condition, before the $a == 2.
  • Check for opening parenthesis, and make sure they are closed.
  • Check for previous statements that uses parenthesis, such as match, switch, if… and make sure they are closed.

syntax error, unexpected token “implements”

Description

implements is a PHP token, which appears inside a class or enum structure. It cannot be find anywhere else.

Example

<?php

X extends Y { }

enum Y extends Z { }

?>

Alternatives

  • Check that a class or an enum have been started.

syntax error, unexpected token “match”, expecting “(”

Description

Since match was introduced as a PHP keyword, it cannot be used anymore to name a class, interface, enum, trait, function or global constant. It may be used to name a class constant, method or property.

Example

<?php

function match($a) {}

?>

Alternatives

  • Change the name match.
  • Make the function a method in a class.

syntax error, unexpected token “match”

Description

In PHP 8.0, the match statement was added to PHP feature: it is a similar feature to switch. match is now a PHP reserved keyword, and, as such, cannot be used everywhere. For example, it cannot be used as a class, function or interface name; it cannot be used in a function call, although it may be used in method call.

Example

<?php

$x = match ($a) {};

?>

Alternatives

  • Change the name to something else than match.

syntax error, unexpected token “namespace”, expecting “{”

Description

The namespace token is one of the first to be used in a script. There is little other command that can be used outside a namespace.

Example

<?php

namespace A

namespace B;

?>

Alternatives

  • Check the previous namespace command, and its final semi colon.
  • Check the previous namespace command, and its associated block.

syntax error, unexpected token “namespace”

Description

The namespace token is one of the first to be used in a script. There is little other command that can be used outside a namespace.

Example

<?php

declare(strict_types=1)

namespace A;

?>

Alternatives

  • Check the previous declare command, and its final semi colon.

syntax error, unexpected token “new”, expecting “)”

Description

This error is a variation of the named parameter typo: the missing semi colon between the name and the value leads to an identifier next to an unrelated operator. The suggestion to use a closing parenthesis is valid, though not the only one.

Example

<?php

foo(arg new B());

class B {}

function foo(B $arg) {}

?>

Alternatives

  • Add the missing : before the new operator.
  • Add the missing ) before the new operator, and add a semi-colon or a comman, depending on the context.

syntax error, unexpected token “private”, expecting “(”

Description

The opening parenthesis that follows a method name is missing. It would be followed by a promoted property declaration, which starts with private.

The same error may apply with the other PHP visibilities, or property options, such as static or readonly.

Example

<?php

class X
{
    public function __construct
        private Y $y,
    ) {
    }
}

?>

Alternatives

  • Add the missing opening parenthesis.

syntax error, unexpected token “private”, expecting “)”

Description

private is not expected at this position in the code, as the previous property $a is not finished. It would be finished with a closing parenthesis ), as suggested by the error message, or a comma, to introduce the next property.

This error message might have other variations, such as protected, public, static, readonly, abstract, final.

Example

<?php

class ProcessController extends AbstractController
{
    public function __construct(
        public A $a
        private B $b,
    ) {
    }
}
?>

Alternatives

  • Add a comma to introduce the next property or argument.
  • Add a closing parenthesis to close the signature and the previous property.

syntax error, unexpected token “private”, expecting “=”

Description

The name of class constant could not use PHP keywords, such as the visibilities private, protected and public; optiosn such as abstract or final, until PHP 8.3. Until then, they would generate a parse error. Such names are generally not used, as they easily sow confusion in the code, at definition but also at usage.

Example

<?php

class X {
    private const string private = 'protected';
}

?>

Alternatives

  • Use another name for the constant.
  • Upgrade to PHP 8.3 or more recent.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “private”, expecting “{”

Description

private and the other visibility options are only seen inside a class or CITE. They mark the start of their definition (property, constant, method), and can only be seen in the body of the CITE.

With an expected opening curly brace, this means the class signature was not finished with the opening curly brace.

Example

<?php

class X 
    private function foo() {}
}

?>

Alternatives

  • Add the opening curly bracket between the class signature and its body.
  • Add the opening curly bracket between the interface signature and its body.
  • Add the opening curly bracket between the trait signature and its body.
  • Add the opening curly bracket between the enum signature and its body.

syntax error, unexpected token “protected”, expecting “{”

Description

protected and the other visibility options are only seen inside a class or CITE. They mark the start of their definition (property, constant, method), and can only be seen in the body of the CITE.

With an expected opening curly brace, this means the class signature was not finished with the opening curly brace.

Example

<?php

class X 
    protected function foo() {}
}

?>

Alternatives

  • Add the opening curly bracket between the class signature and its body.
  • Add the opening curly bracket between the interface signature and its body.
  • Add the opening curly bracket between the trait signature and its body.
  • Add the opening curly bracket between the enum signature and its body.

syntax error, unexpected token “public”, expecting “]”

Description

Inside the square brackets of an array index, PHP expects an expression identifying the key, followed by the closing ]. public is a reserved word: it can only be used as a visibility modifier, never as the start of an expression, such as an unquoted array key. PHP therefore reports that it was still expecting ] to close the array access.

The same message also appears whenever a previous [ was left unclosed, and a later, unrelated public is the first token that cannot continue the pending index expression.

Example

<?php

$arr = [1, 2, 3];
$y = $arr[public];

?>

Alternatives

  • Quote the key if a string was intended: $arr['public'].
  • Use a constant or variable holding the intended key instead of the bare word.
  • Check that every previous [ in the file has a matching ].
  • [syntax-error,-unexpected-token-“::”,-expecting-“]”](syntax-error,-unexpected-token-::,-expecting-].html)
  • [syntax-error,-unexpected-token-“class”,-expecting-“]”](syntax-error,-unexpected-token-class,-expecting-].html)
  • [syntax-error,-unexpected-token-“if”,-expecting-“]”](syntax-error,-unexpected-token-if,-expecting-].html)

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “public”, expecting “{”

Description

public and the other visibility options are only seen inside a class or CITE. They mark the start of their definition (property, constant, method), and can only be seen in the body of the CITE.

With an expected opening curly brace, this means the class signature was not finished with the opening curly brace.

Example

<?php

class X 
    public function foo() {}
}

?>

Alternatives

  • Add the opening curly bracket between the class signature and its body.
  • Add the opening curly bracket between the interface signature and its body.
  • Add the opening curly bracket between the trait signature and its body.
  • Add the opening curly bracket between the enum signature and its body.

syntax error, unexpected token “public”

Description

The keyword public is expected in a PHP method body, but not in the body of a method or a function.

This may apply to the other visibilies, protected and private, and also to some other method options, such as abstract.

Example

<?php

class A {
    function foo() {
        public $x;
    }
}
?>

Alternatives

  • Close the initial method body, before creating another property or method with a visibility.
  • Remove the public keyword in the body of the method.

syntax error, unexpected token “use”, expecting “,” or “;”

Description

The previous use command was not properly finished with a semi-colon.

Example

<?php

use A as B
use C as D;

?>

Alternatives

  • Add another use case, with a comma, and then finish the instruction with ;.
  • Finish the previous use case, with a semi colon ;.
  • Remove the next use keyword, and replace it with a comma.

syntax error, unexpected token “use”, expecting “{”

Description

The namespace command was now finished properly. It could be finished with a semi-colon ;, and use would be the next instruction. Or it could go be followed by a block of definition, that starts with an open curly bracket.

Example

<?php

namespace A\B\C

use D\E;

?>

Alternatives

  • Finish the namespace with a semi colon.
  • Add a block to the namespace, that encompass the use instruction.

syntax error, unexpected token “use”

Description

use expression must be place at the top level of a file, a namespace block, or a class, enum or trait block.

In particular, when set in a structure such as a foreach, it yields a syntax error.

Besides that, the command is actually valid.

Example

<?php 
if ($a) {
    use stdClass as A;
}

?>

Alternatives

  • Move the use out of the if structure.
  • Remove the use command.

syntax error, unexpected token “{”, expecting “)”

Description

This is a side effect of the removed support for curly braces as array and string offset syntax. Here, the parser was reading a function call’s argument list and reached the point where it expects the closing parenthesis, but found the leftover curly brace instead. This exact wording appears since PHP 8.0, when curly-brace offset access was removed from the language.

Example

<?php
    echo foo($variable{$index});
?>

Alternatives

  • Refactor the curly braces to square ones.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “{”, expecting “,” or “;”

Description

PHP 8.4 introduced property hooks, which allow defining getters and setters for properties directly in the property definition. Previous PHP versions did not support that syntax, and yield this error.

Example

<?php

class A {
    public $prop {
        get { return A; }
        set { echo __METHOD__, \n; }
    }
}

?>

Alternatives

  • Upgrade to PHP 8.4.
  • Remove the property hooks.
  • Move the property hooks to a method.
  • Move the property hooks to a magic method.

syntax error, unexpected token “{”, expecting “;”

Description

This is a side effect of the removed support for curly braces as array and string offset syntax. Here, the parser has just finished reading a statement and expects a terminating ;, but instead finds a leftover curly brace that used to introduce an offset expression. This exact wording appears since PHP 8.0, when curly-brace offset access was removed from the language.

Example

<?php
    $variable{$index} = 'value';
?>

Alternatives

  • Refactor the curly braces to square ones.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected token “{”, expecting variable

Description

With the last comma in the signature of the method, PHP expects another parameter after it, or the end of the signature with a closing parenthesis.

Example

<?php

class A {
    public function __construct($b,
     { }
}
?>

Alternatives

  • Add a closing parenthesis.
  • Add another parameter, then a closing parenthesis.

syntax error, unexpected token “{”

Description

A syntax error is a generic error, where PHP could not compile the code. Here are some classic typo or seemingly valid code that leads to this error.

  • Since PHP 8.4, array syntax with curly braces are not valid anymore. It used to yield a warning, and it is now totally abandoned.
  • A missing closing parenthesis in a crowded parenthesis space, leads to an error in the next block.

Example

<?php

// the curly bracket array syntax has been removed
$a{1} = 2;

// curly brackets start a block, and blocks are not allowed inside expressions (the && )
$a == 1 && {1} : 3;

?>

Alternatives

  • Move to the square bracked array syntax only.
  • Add the missing closing parenthesis to the if() statement.

syntax error, unexpected token “}”, expecting “;” or “{”

Description

PHP found a closing curly bracket, but did not encounter its opening equivalent. Since the problem appears in the signature of a method, there are two suggestions: make the method abstract, with a semi-colon ‘;’, or give the method a full body, with the opening curly bracket.

Example

<?php

class A
{
    public function __construct() 
    }
}
?>

Alternatives

  • Add an opening curly bracket ‘{’ before the closing one. Possibly, fill the body of the method.
  • Replace the closing curly bracket with a semi colon. The method, and possibly the class, must now be abstract.

syntax error, unexpected token “}”

Description

The closing curly bracket usually mark the end of a block of instructions.

When it is reported as an error, it means that the previous instruction was not closed as expected. For example, when a semi-colon was not forgotten on the previous line.

Example

<?php

// print needs a ; at the end of the command
if ($c == 3) { print 'OK'.PHP_EOL }

// The curly brackets are balanced, but not the parenthesis
if (in_array(1, [2, 4]) {}

?>

Alternatives

  • Check if the previous line need a semi-colon ;.

syntax error, unexpected variable “$%s”, expecting “)”

Description

In a function, method or closure signature, each parameter must be separated from the next one by a comma. Here, the comma between $a and $b is missing, so once PHP has parsed $a as a complete parameter, it expects either another comma or the closing parenthesis of the argument list; instead it finds another variable.

Example

<?php

function foo($a $b) {}

?>

Literal Examples

  • syntax error, unexpected variable “$b”, expecting “)”

Alternatives

  • Add the missing comma between the two parameters.
  • Remove the extra variable if it was left over from editing.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected variable “$task”, expecting “)”

Description

In a function, method or closure signature, each parameter must be separated from the next one by a comma. Here, the comma between $name and $task is missing, so once PHP has parsed $name as a complete, typed parameter, it expects either another comma or the closing parenthesis of the argument list; instead it finds another variable, $task.

This is the generic “unexpected variable, expecting )” message, reported here with the concrete variable name found in the offending code, $task.

Example

<?php

function schedule(string $name $task) {}

?>

Alternatives

  • Add the missing comma between the two parameters.
  • Remove the extra variable if it was left over from editing.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected variable “$this”, expecting “;” or “{”

Description

An abstract method’s signature must be terminated with a semicolon, since it has no body, and a concrete method’s signature must be followed by a { opening the body. Here, the variable $this was found right after the closing parenthesis of the argument list, where PHP expected one of those two terminators.

$this cannot appear here in any case: it is a read-only pseudo-variable, automatically bound to the current object inside a non-static method, and it can never be declared, assigned or used as a standalone statement outside of an expression.

Example

<?php

abstract class X {
    abstract function foo() $this;
}

?>

Alternatives

  • Remove $this and terminate the abstract method with a semicolon.
  • If a method body was intended, replace $this with { and the method’s code.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

syntax error, unexpected variable “%s”, expecting “(”

Description

In a function definition, the name of the function is separated from the argument list by an opening parenthesis. This is missing here. This applied to closures, arrow functions and methods’ signatures.

Example

<?php

    function foo $name: , $value = 1) {}
    function bar ) {}

?>

Alternatives

  • Add the missing opening parenthesis.
  • Provide a value for the parameter name in the functioncall.

The “Generator” class is reserved for internal use and cannot be manually instantiated

Description

Generator is a PHP native class. It is automagically created when a function or method uses the yield or yield from keyword. There is no other ways to create such an object.

In fact, generator is also a final class, so it cannot be extended too.

Example

<?php

new Generator();

?>

Alternatives

  • Use composition to use this class in another class.

The $context parameter has no effect for finfo_buffer()

Description

finfo_buffer() (and finfo::buffer()) accept an optional $context parameter, mirroring the signature of stream-related functions. Unlike finfo_file(), which does use a stream context to open the file it inspects, finfo_buffer() operates directly on an in-memory string and never opens a stream, so the $context argument has never had any effect.

As of PHP 8.5.0, passing a value for $context raises a deprecation notice to reflect that fact.

Example

<?php

$finfo = new finfo(FILEINFO_MIME_TYPE);
$context = stream_context_create();

echo $finfo->buffer('some data', FILEINFO_NONE, $context);

?>

Alternatives

  • Stop passing a $context argument to finfo_buffer()/finfo::buffer().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See finfo_buffer

the $escape parameter must be provided, as its default value will change, either explicitly or via SplFileObject::setCsvControl()

Description

SplFileObject::fgetcsv() and SplFileObject::fputcsv() take an $escape character used to escape the enclosure character inside CSV fields, currently defaulting to \ (backslash) – a default that PHP 9.0 will change to an empty string, disabling escaping entirely by default, to better match RFC 4180 and other CSV parsers.

As of PHP 8.4, calling fgetcsv()/fputcsv() on a SplFileObject without an explicit $escape – and without having set one explicitly via SplFileObject::setCsvControl() either – emits this deprecation notice, so the pending default change does not silently alter behaviour later.

Example

<?php

file_put_contents('/tmp/data.csv', "a,b,c\n");

$file = new SplFileObject('/tmp/data.csv');
$file->setFlags(SplFileObject::READ_CSV);

// No $escape argument, and setCsvControl() was never called to set
// one explicitly either, so the (soon to change) default is used.
var_dump($file->fgetcsv());

?>

Literal Examples

  • SplFileObject::fgetcsv(): the $escape parameter must be provided, as its default value will change, either explicitly or via SplFileObject::setCsvControl()

Alternatives

  • Pass $escape explicitly on every fgetcsv()/fputcsv() call, e.g. $file->fgetcsv(‘,’, ‘“’, ‘\’).
  • Call SplFileObject::setCsvControl() once with the escape character, so every later fgetcsv()/fputcsv() call already has it set.
  • Decide now whether the code needs backslash-escaping (pass ‘\’) or the future default (pass ‘’) and stop depending on the implicit default either way.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See fputcsvEscape

the $escape parameter must be provided as its default value will change

Description

The $escape parameter of various PHP functions that deal with CSV files will change in PHP 9.0. The current default value is \ (backslash), and it will be changed to an empty string. To be ready for that version, it is recommended to explicitly set that value, so as to preserve the previous behavior, with a \, or move to the new one, with an empty string.

Example

<?php

$fp = fopen(export.csv, w);
fputcsv($data);

?>

Alternatives

  • Add the 5th parameter in the fputcsv() or fgetcsv() calls.
  • Add the named parameter escape in the calls.
  • Test your application with escape set to empty string, and PHP 8.4+.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See fputcsvEscape

the $key_length parameter is deprecated as it is either ignored or truncates the key

Description

openssl_pkey_derive() computes a shared secret from a private key and a peer’s public key (for DH or ECDH key agreement), and accepts an optional $key_length argument that was documented as controlling the length of the derived secret.

In practice, this parameter is either ignored entirely (when it is larger than or equal to the natural size of the underlying prime/curve) or silently truncates the derived key (when it is smaller), which can give a false sense of control over the output length and lead to weakened, truncated secrets being used unknowingly. As of PHP 8.5.0, passing a value for $key_length raises a deprecation notice.

Example

<?php

$sharedSecret = openssl_pkey_derive($peerPublicKey, $privateKey, 32);

?>

Alternatives

  • Stop passing $key_length to openssl_pkey_derive(), and if a specific length is required, derive it explicitly from the full secret afterwards (e.g. with a KDF such as hash_hkdf()).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See openssl_pkey_derive

The (real) cast operator has been removed, use (float) instead. Both operator looked like synonyms, and were providing the same feature.

Description

The (real) cast operator was deprecated in PHP 7.x and is completely removed since PHP 8.0. It may be replaced with (float).

Example

<?php

$float = (real) "1.333";

?>

Alternatives

  • Use (float) instead.

In previous PHP versions, this error message used to be :ref:the-(real)-cast-is-deprecated,-use-(float)-instead.

The (real) cast is deprecated, use (float) instead

Description

The (real) cast operator is deprecated since PHP 7.4. It was completely removed in PHP 8.0. (real) was a synonym of (float), although there is no such notion in PHP.

Example

<?php

$float = (real) 1.333;

?>

Alternatives

  • Use (float) instead.

In more recent PHP versions, this error message is now :ref:the-(real)-cast-has-been-removed,-use-(float)-instead.

The (unset) cast is deprecated

Description

Removing a variable, a property or an array index with the cast operator (unset) is deprecated since PHP 7.4, and will be removed in PHP 8.0. It is recommnded to do it with the unset() function.

Example

<?php

(unset) $x;

?>

Alternatives

  • Use the unset() function to remove variables.
  • Assign null to the variable.

In more recent PHP versions, this error message is now :ref:the-(unset)-cast-is-no-longer-supported.

The (unset) cast is no longer supported

Description

Removing a variable, a property or an array index with the cast operator (unset) was removed in PHP 8.0. It has to be done with the unset() function.

Example

<?php

(unset) $x;

?>

Alternatives

  • Use the unset() function to remove variables.
  • Assign null to the variable.

In previous PHP versions, this error message used to be :ref:the-(unset)-cast-is-deprecated.

The “salt” option has been ignored, since providing a custom salt is no longer supported

Description

password_hash() used to accept a salt option, which let the caller choose the salt of the hash. This is no longer supported: the option is ignored, and password_hash() generates a random salt itself. The hash is still returned, so the code keeps running, but the custom salt does not appear in it.

A custom salt was a weak practice, as a fixed or badly chosen salt makes it easier to attack many hashes at once. Since the salt is stored inside the hash, password_verify() works without the caller managing it.

Example

<?php

// The salt option is ignored: password_hash() generates its own salt
$hash = password_hash('password', PASSWORD_DEFAULT, ['salt' => 'a-custom-salt-value']);

?>

Literal Examples

  • password_hash(): The “salt” option has been ignored, since providing a custom salt is no longer supported

Alternatives

  • Remove the salt option. password_hash() already generates a random salt for each hash.
  • To check a password, use password_verify(), which reads the salt from the stored hash.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The "ssl_method" option is deprecated. Use "ssl" stream context options instead

Description

SoapClient accepts an 'ssl_method' constructor option to pick which SSL/TLS version to use, predating PHP’s general-purpose stream context SSL options. In practice it offers little control: SOAP_SSL_METHOD_TLS and SOAP_SSL_METHOD_SSLv23 both just mean ‘the default’, SOAP_SSL_METHOD_SSLv2 always fails since PHP no longer supports SSL 2, and SOAP_SSL_METHOD_SSLv3 selects a protocol considered insecure for years.

As of PHP 8.1, passing 'ssl_method' emits this deprecation notice; the far more capable 'ssl' stream context options (in particular crypto_method) already cover the same need for every other stream-based extension, including individual TLS versions that ssl_method cannot select at all.

Example

<?php

$client = new SoapClient(null, [
    'location' => 'https://example.com/soap',
    'uri'      => 'https://example.com/soap',
    // Selecting the TLS version through this option is deprecated.
    'ssl_method' => SOAP_SSL_METHOD_TLS,
]);

?>

Literal Examples

  • SoapClient::__construct(): The “ssl_method” option is deprecated. Use “ssl” stream context options instead

Alternatives

  • Build a stream context with the desired ‘ssl’ => [‘crypto_method’ => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT] (or similar) and pass it via the ‘stream_context’ constructor option instead.
  • Drop ‘ssl_method’ entirely if only the platform default TLS version is needed – that is what SOAP_SSL_METHOD_TLS already resolved to.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The "yield" expression can only be used inside a function

Description

yield is what turns a function into a generator: it can only appear inside a function body (a named function, a method, a closure, or an arrow function). Using it directly in the top-level script code – outside of any function – is meaningless, since there is no generator for it to belong to, and PHP rejects it at compile time.

The same error is raised for any yield (or yield from) written at the top level of an included or required file, as long as it is not nested inside a function definition there.

Example

<?php

yield 1;

?>

Alternatives

  • Wrap the code that needs to yield values inside a generator function, and call that function instead.
  • Remove the yield statement if it was left over by mistake.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The __sleep() serialization magic method has been deprecated.

Description

Class serialization in PHP has had multiple mechanism introduced to control its behaviour by userland. Initially with the __sleep() and __wakeup() magic methods, then with the Serializable interface and finally with __serialize() and __unserialize().

In the end, the __serialize and __unserialize methods must be used, instead of __sleep and __wakeup.

Example

<?php

class X {
    function __sleep() {}
}

?>

Alternatives

  • Rename the method to __serialize.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The __wakeup() serialization magic method has been deprecated.

Description

Class serialization in PHP has had multiple mechanism introduced to control its behaviour by userland. Initially with the __sleep() and __wakeup() magic methods, then with the Serializable interface and finally with __serialize() and __unserialize().

In the end, the __serialize and __unserialize methods must be used, instead of __sleep and __wakeup.

Example

<?php

class X {
    function __sleep() {}
}

?>

Alternatives

  • Rename the method to __unserialize.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The arguments array must contain %d items, %d given

Description

When using vsprintf(), the second argument is an array which must hold the same number of elements than there are placeholders in the format string (aka, the first argument).

Example

<?php

    var_dump(vsprintf("%04d-%02d-%02d", []));

?>

Literal Examples

  • The arguments array must contain 3 items, 0 given

Alternatives

  • Add the needed elements to the array.
  • Remove the superfluous placeholders in the format string.

The backtick (`) operator is deprecated, use shell_exec() instead

Description

The back tick operator \ is the equivalent to the functionshell_exec()`. It is being deprecated since PHP 8.5.

Example

<?php

echo `ls`;

?>

Alternatives

  • Use shell_exec() instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See backtick

The behavior of unparenthesized expressions containing both ‘.’ and ‘+’/‘-’ will change in PHP 8: ‘+’/‘-’ will take a higher precedence

Description

+/- and . operators used to have the same priority. This meant that expressions which mixed them would see them executed from left to right. This was confusing, so PHP 8.0 has made the addition the highest priority, closer to human way of reading the code.

Example

<?php

$b = 2;
$a = 'a '. $b + 1;

?>

Alternatives

  • Add parenthesis to make the code less ambiguous.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See dotAndMinus, dotAndPlus

The behavior of unparenthesized expressions containing both ‘.’ and ‘<<’/‘>>’ will change in PHP 8: ‘<<’/‘>>’ will take a higher precedence

Description

<</>> and . operators used to have the same priority. This meant that expressions which mixed them would see them executed from left to right. This was confusing, so PHP 8.0 has made the addition the highest priority, closer to human way of reading the code.

Example

<?php

$b = 2;
$a = 'a '. $b >> 1;

?>

Alternatives

  • Add parenthesis to make the code less ambiguous.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See dotAndBitshift

The connection has no charset associated

Description

This error appears when PHP cannot retrieve the character set used by the connection to MySQL. The mysqli_get_charset() function tries to fetch the data from the connexion, but the result was not usable.

Such error is probably circumstancial: the server may have gone away, or crashed, leading to no answer about charset.

Example

<?php

    $db = mysqli_init();
    $db->real_connect(localhost,user,password,test);
    var_dump($db->get_charset()); 

?>

Alternatives

  • Check the server health.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The driver_version property is deprecated

Description

mysqli_driver::$driver_version reads back the internal constant MYSQLI_VERSION_ID, which sounds like it should report the version of the underlying MySQL client library (mysqlnd or libmysqlclient) but does not: it is a hardcoded value (101009) left over from mysqli’s early days as a standalone PECL extension, and it has not tracked anything meaningful for a long time.

As of PHP 8.1, reading this property emits a deprecation notice; it keeps returning the same frozen value for now, ahead of being removed in a future version.

Example

<?php

$driver = new mysqli_driver();

// Reading this property is deprecated; it has always just repeated
// PHP's own version number, not any driver-specific version.
var_dump($driver->driver_version);

?>

Literal Examples

  • The driver_version property is deprecated

Alternatives

  • Use PHP_VERSION or PHP_VERSION_ID directly if a PHP version number was actually wanted.
  • Use mysqli_get_client_info() / mysqli_driver::$client_info if the actual client library version is needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The each() function is deprecated. This message will be suppressed on further calls

Description

The function each was deprecated in PHP 7.x and removed in PHP 8.0. It was mainly used in loops like the above, and could be replaced advantageously with a foreach structure.

Example

<?php

$array = ['a', 'b'];
while(list($key, $value) = each($array)) {
    print "$key => $value\n";
}

?>

Alternatives

  • Replace the while loop with a foreach one.
  • Replace the loop with a call to one of the array function.
  • Traverse the array with a yield or yield from call.
  • Use an iterator to traverse the array.

In more recent PHP versions, this error message is now :ref:call-to-undefined-function-each().

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See each

The filter.default ini setting is deprecated

Description

filter.default (with filter.default_flags) names a filter that PHP applies automatically to the $_GET, $_POST, $_COOKIE, $_REQUEST and $_SERVER superglobals themselves, as well as to filter_input() calls that don’t specify their own filter. Its own default is unsafe_raw (no filtering), but changing it to anything else effectively resurrects a magic-quotes-like behaviour: input gets silently sanitized (or mangled) based on a global setting the code reading $_GET/$_POST may not even be aware of, which was one of the classic sources of subtle bugs and security issues in old PHP applications.

As of PHP 8.1, setting filter.default to anything other than unsafe_raw emits this deprecation notice at startup. The setting keeps working for now, but filter.default (and filter.default_flags) are expected to be removed in PHP 9.0.

Example

<?php

// filter.default is PHP_INI_SYSTEM|PHP_INI_PERDIR, so it cannot be
// changed at runtime with ini_set() -- only in php.ini, .user.ini,
// httpd.conf, or via -d on the command line, for example
//   php -d filter.default=int script.php
var_dump(ini_get('filter.default'));

?>

Literal Examples

  • The filter.default ini setting is deprecated

Alternatives

  • Leave filter.default at its default, unsafe_raw, and call filter_var()/filter_input() explicitly wherever input needs sanitizing or validating.
  • Search the codebase for any place relying on the implicit global filter and make the filtering explicit there instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The float %.*H is not representable as an int, cast occurred

Description

When a float is cast to int – explicitly with (int)/intval(), or implicitly wherever an integer is required, such as an array offset or a bitwise operator – and the value is outside the range representable by PHP_INT_MIN/PHP_INT_MAX, or is NAN or INF, PHP cannot produce a meaningful integer.

Rather than silently returning an arbitrary or platform-dependent bit pattern, PHP emits this warning and returns 0 for NAN/INF, or a value obtained by taking the float modulo the 64-bit integer range for very large finite values – in both cases, a value with no reliable relationship to the original float.

Example

<?php

var_dump((int) 1.0E+20);
// int(0) on 64-bit, and the value bears no relation to 1.0E+20

var_dump((int) NAN);
// int(0)

var_dump((int) INF);
// int(0)

?>

Literal Examples

  • The float 1.0E+20 is not representable as an int, cast occurred
  • The float NAN is not representable as an int, cast occurred
  • The float INF is not representable as an int, cast occurred

Alternatives

  • Check the float against PHP_INT_MIN/PHP_INT_MAX (and against is_nan()/is_infinite()) before casting it.
  • Keep the value as a float or as a string if it may exceed the integer range.
  • Use BCMath or GMP if arbitrary-precision integers are required.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The float-string “%s” is not representable as an int, cast occurred

Description

The string contains a numeric value, that could be parsed, even partially. Yet, the resulting number is bigger than the larger supported integer PHP_INT_MAX. At that point, PHP replace the parse numeric value to the maximum integer value.

The problem does not happen with float numbers, which are converted to INF infinity when they can’t be represented anymore.

This problem is often related to the presence of the e character in the string, which yield a possible float number.

Example

<?php

var_dump((int) 9E82);
//9223372036854775807

var_dump((float) 9E82);
//float(9.0E+82)

?>

Literal Examples

  • The float-string “9E82” is not representable as an int, cast occurred

Alternatives

  • Use the string, rather than convert it to an integer.
  • Check if the string can be converted before using the cast.
  • Compare the resulting value with PHP_INT_MAX: it might be very far from the expected conversion.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The magic method %s::%s() must have public visibility

Description

The magic methods must have the public visibility, as their features are available to external sources. It may also use the default visibility.

Example

<?php

class X {
    private function __isset($x) {}
    protected function __get($x) {}
}

?>

Literal Examples

  • The magic method X::__isset() must have public visibility
  • The magic method X::__get() must have public visibility
  • The magic method X::__set() must have public visibility

Alternatives

  • Set the visibility to public.
  • Remove the visibility, to use the default of public.
  • Remove the magic method.

The maximum representable range is 2_147_483_647 seconds (roughly 68 years)

Description

PHP 8.6 introduces Time\Duration, a value object representing a span of time as whole seconds plus nanoseconds. Internally, the number of seconds is validated so that the whole duration, expressed in nanoseconds, still fits in a single platform integer (zend_long).

On a 32-bit build of PHP, where zend_long is only 32 bits wide, that ties the maximum number of seconds to PHP_INT_MAX on that platform: 2_147_483_647 seconds, or roughly 68 years. Passing a larger value throws a Time\TimeException. On 64-bit builds, the equivalent, larger limit is described separately (see the-maximum-representable-range-is-9_223_372_035-seconds-(roughly-292-years)).

Example

<?php

use Time\Duration;

// on a 32-bit build of PHP
$duration = Duration::fromSeconds(3_000_000_000);

?>

Literal Examples

  • The maximum representable range is 2_147_483_647 seconds (roughly 68 years)

Alternatives

  • Keep durations built from Duration::fromSeconds() (or the constructor) within PHP_INT_MAX seconds for the target platform.
  • On 32-bit systems, split very long spans of time into smaller Duration values, or use DateInterval instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The maximum representable range is 9_223_372_035 seconds (roughly 292 years)

Description

PHP 8.6 introduces Time\Duration, a value object representing a span of time as whole seconds plus nanoseconds. Even though a 64-bit zend_long could count seconds far beyond any realistic duration, $seconds is deliberately capped at 9_223_372_035, so that the whole duration can still be expressed as a single count of nanoseconds without overflowing a 64-bit integer (roughly PHP_INT_MAX divided by one billion). That works out to about 292 years.

Passing a larger number of seconds to Duration::fromSeconds() (or the constructor) throws a Time\TimeException, instead of silently producing a value that could overflow later.

Example

<?php

use Time\Duration;

$duration = Duration::fromSeconds(9_223_372_036);

?>

Literal Examples

  • The maximum representable range is 9_223_372_035 seconds (roughly 292 years)

Alternatives

  • Keep durations within 9_223_372_035 seconds (about 292 years).
  • For spans of time longer than that, model them with something other than Duration, such as separate DateTimeImmutable endpoints.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The modifiers of the trait method %s() are changed, but this method does not exist. Error

Description

Inside the use block of a class, a conflict-resolution rule can change the visibility of a trait method without renaming it, by writing method as visibility; – with no trait name before the method, and no new name after the modifier.

Here, bar is not qualified with a trait name, so PHP looks for a method called bar in every trait used by the class. Since none of them declares it, and the rule does not introduce an alias (there is no new name after protected), PHP reports that the modifiers of a non-existent method were changed, rather than reporting a missing alias target.

Example

<?php

trait A {
    public function foo() {}
}

class C {
    use A {
        bar as protected;
    }
}

?>

Literal Examples

  • The modifiers of the trait method bar() are changed, but this method does not exist. Error

Alternatives

  • Fix the typo in the method name so it matches an existing method of one of the used traits.
  • Remove the rule if changing the visibility of that method is no longer needed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The MT_RAND_PHP variant of Mt19937 is deprecated

Description

Random\Engine\Mt19937 (and the legacy mt_srand()/mt_rand() functions) support two variants of the Mersenne Twister algorithm, selected via the $mode argument: MT_RAND_MT19937, the correct, standard implementation, and MT_RAND_PHP, a non-standard variant kept only for backward compatibility with PHP’s own mt_rand() behaviour prior to PHP 7.1. MT_RAND_PHP uses a biased scaling algorithm and, before PHP 8.2, exhibited undefined behaviour for some seed values.

As of PHP 8.3, constructing an engine (or seeding the legacy PRNG) with MT_RAND_PHP emits this deprecation notice; the special-cased, non-standard variant exists purely to reproduce historical output and should not be used in new code.

Example

<?php

// MT_RAND_PHP selects PHP's own historical, biased reimplementation
// of the Mersenne Twister instead of the correct, standard one.
$engine = new Random\Engine\Mt19937(1234, MT_RAND_PHP);
$randomizer = new Random\Randomizer($engine);

var_dump($randomizer->getInt(0, 100));

?>

Alternatives

  • Use MT_RAND_MT19937 (or simply omit the $mode argument, since it is the default) to get the correct, standard Mersenne Twister implementation.
  • For new code, prefer a modern engine such as Random\Engine\Secure via the Random\Randomizer API instead of seeding Mt19937 manually.
  • Only keep MT_RAND_PHP where reproducing PHP’s historical, legacy random sequence bit-for-bit is an explicit requirement.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The parent constructor was not called: the object is in an invalid state

Description

When extending certain PHP native classes, the child class must call the parent constructor to finish the instantiation of the object.

The problem is not detected at instantiation time, but later, as soon as any of the parent resources are used, but found to be in invalid state.

PHP does not automatically call the parent constructor when creating a child instance. It must be explicit in the code.

Some classes that needs such initialisation are: SplFileObject, SplDirectory, GlobIterator. The list is not exhaustive.

Example

<?php
// PHP bug 8318
class Bug8318 extends \SplFileObject
{
    public function __construct()
    {
    }

    public function fpassthru(): int
    {
        return 0;
    }
}

$cl = new Bug8318;
try {
    $cl->fpassthru();
} catch (\Error $e) {
    var_dump($e);
}
?>

Alternatives

  • Call the parent constructor.
  • Use another parent class.

The PDO extension must be loaded first in order to load PDO drivers

Description

Driver extensions such as pdo_mysql, pdo_sqlite or pdo_pgsql are separate shared extensions from the core pdo extension: at startup, each of them registers itself with the core PDO extension so that it can be looked up later by PDO::getAvailableDrivers() and by the new PDO("driver:...") DSN syntax.

That registration only works if the core pdo extension has already finished loading and initializing by the time the driver extension’s own module init runs. If pdo was never loaded at all, for instance because it was built as a shared extension and its extension=pdo line is missing, commented out, or ordered after the driver in php.ini on a setup old enough not to resolve this automatically, PHP fails to start with this fatal error the moment it tries to register the driver.

Example

; php.ini, with the pdo shared extension missing or disabled,
; while a PDO driver extension is still enabled

;extension=pdo
extension=pdo_sqlite

Literal Examples

  • The PDO extension must be loaded first in order to load PDO drivers

Alternatives

  • Make sure extension=pdo (or a statically-built pdo) is enabled; most current PHP builds compile pdo statically or resolve module dependencies automatically, so this is mostly seen on custom or older builds.
  • If php.ini lists extensions manually, make sure pdo is loaded before any pdo_* driver extension.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The PDO::FETCH_SERIALIZE mode is deprecated

Description

Combined with PDO::FETCH_CLASS, the PDO::FETCH_SERIALIZE flag was meant to fetch a row by unserialize()-ing one of its columns into an instance of the target class, relying on that class implementing the Serializable interface. Beyond depending on Serializable – which is itself being phased out in favour of __serialize()/__unserialize() – the flag has a long-standing implementation bug that makes it not actually usable as documented.

As of PHP 8.1, setting or using this fetch mode emits this deprecation notice, ahead of its planned removal in PHP 9.0.

Example

<?php

$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE t (x TEXT)');
$stmt = $pdo->query('SELECT x FROM t');

// Combined with FETCH_CLASS, this flag was meant to automatically
// unserialize() the raw column into the target class.
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_SERIALIZE, 'stdClass');

?>

Literal Examples

  • PDOStatement::setFetchMode(): The PDO::FETCH_SERIALIZE mode is deprecated
  • PDOStatement::fetch(): The PDO::FETCH_SERIALIZE mode is deprecated

Alternatives

  • Fetch the raw column value with a plain fetch mode, then call unserialize() on it explicitly and assign the result where needed.
  • Store structured data as JSON instead of a serialized PHP value, and decode it with json_decode() after fetching.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The predefined locally scoped $http_response_header variable is deprecated, call http_get_last_response_headers() instead

Description

The PHP variable $http_response_header is automagically created after a call to a remote resource. It contains the returned headers, for further analysis. This variable is deprecated since PHP 8.5, and will disappear in PHP 9.0. It should be replaced with a call to http_get_last_response_headers().

Example

<?php

    file_get_contents(https://www.php.net/);
    var_dump($http_response_header); // variable is populated in the local scope

?>

Alternatives

  • Call http_get_last_response_headers() instead of relying on the variable.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See http_response_header

The return value of function %s() should either be used or intentionally ignored by casting it as (void)%S code

Description

.

Example

<?php

#[NoDiscard]
function foo() {
    return 1;
}

foo();

?>

Literal Examples

  • The return value of function foo() should either be used or intentionally ignored by casting it as (void)

Alternatives

  • Add the (void) cast to the function call, so as to ignore the returned value.
  • Store the result of the function call in a variable and use it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The return value of function %s() should either be used or intentionally ignored by casting it as (void)%S

Description

When a function has the NoDiscard attribute, it means that its returned value must be collected and used. When the value is simply ignored, PHP stops execution with a fatal error.

Example

<?php

#[\NoDiscard]
function foo() {
    return 1;
}

foo();

?>

Alternatives

  • Store the returned value in a variable, and use it to check the returned value.
  • Use the function call as an argument of another function.
  • Use the (void) cast, to explicitly ignore the result.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The return value of method %s::%s() should either be used or intentionally ignored by casting it as (void)%S

Description

When a method has the NoDiscard attribute, it means that its returned value must be collected and used. When the value is simply ignored, PHP stops execution with a fatal error.

Example

<?php

#[\NoDiscard]
function foo() {
    return 1;
}

foo();

?>

Alternatives

  • Store the returned value in a variable, and use it to check the returned value.
  • Use the function call as an argument of another method.
  • Use the (void) cast, to explicitly ignore the result.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified %s is malformed%s%s%s

Description

This is the detailed variant of the parsing error raised by the native URI extension, introduced in PHP 8.5, when a string handed to Uri\Rfc3986\Uri or Uri\WhatWg\Url cannot be parsed as a valid URI/URL. In addition to naming what was being parsed (URI or URL), the extra placeholders append the detailed diagnostic produced by the underlying parser, such as the specific validation error and, when possible, a pointer to the offending part of the string.

Example

<?php

use Uri\Rfc3986\Uri;

try {
    $uri = new Uri('https:// example.com');
} catch (\Uri\InvalidUriException $e) {
    echo $e->getMessage();
}

?>

Alternatives

  • Fix the malformed component reported in the exception message before constructing the URI.
  • Validate or normalize untrusted input before passing it to the Uri classes.
  • Call Uri\InvalidUriException::getErrors() to inspect the individual validation errors programmatically.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified %s is malformed

Description

The native URI extension, introduced in PHP 8.5, throws this exception when the string passed to Uri\Rfc3986\Uri or Uri\WhatWg\Url cannot be parsed as a valid URI/URL at all, and no further diagnostic detail is available to attach to the message. %s names what was being parsed (URI for the RFC 3986 parser, URL for the WHATWG parser).

Example

<?php

use Uri\Rfc3986\Uri;

try {
    $uri = new Uri('not a valid uri');
} catch (\Uri\InvalidUriException $e) {
    echo $e->getMessage();
}

?>

Literal Examples

  • The specified URI is malformed
  • The specified URL is malformed

Alternatives

  • Check the input string against the expected URI/URL syntax before parsing it.
  • Wrap the constructor call in a try/catch block and report or discard invalid input gracefully.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified scheme is malformed

Description

A URI scheme must be a non-empty string starting with a letter, followed only by letters, digits, +, - or . (RFC 3986, section 3.1). Uri\Rfc3986\Uri::withScheme() and Uri\Rfc3986\UriBuilder::setScheme() validate this and throw when the value does not fit that grammar — including an empty string, as shown above.

The WHATWG-flavored Uri\WhatWg\Url::withScheme() reports the same message, though a parse failure (rather than a modification failure) additionally appends the specific WHATWG validation error in parentheses, e.g. The specified scheme is malformed (MissingSchemeNonRelativeUrl).

Example

<?php

$uri = Uri\Rfc3986\Uri::parse('https://example.com');

$uri = $uri->withScheme('');

?>

Alternatives

  • Use a scheme made only of ASCII letters, digits, +, - and ., starting with a letter.
  • Do not pass an empty string to withScheme() / setScheme().

In more recent PHP versions, this error message is now :ref:failed-to-update-the-scheme.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified URI is malformed

Description

Uri\Rfc3986\Uri::__construct() and Uri\Rfc3986\Uri::parse() reject any input string that does not conform to the RFC 3986 URI grammar as a whole — as opposed to a failure on a single component such as the scheme or host. An empty scheme before ://, as above, is one such case, but any structurally invalid URI string triggers it.

The WHATWG-flavored Uri\WhatWg\Url (used via Uri\WhatWg\Url::parse() or its constructor) throws Uri\WhatWg\InvalidUrlException with the same base message, but appends the specific WHATWG validation failure in parentheses, e.g. The specified URI is malformed (HostMissing), and exposes the full list of validation errors through the exception’s errors property.

Example

<?php

new Uri\Rfc3986\Uri('://example.com');

?>

Alternatives

  • Validate or normalize the URI string before parsing it, or wrap the parse call in a try/catch.
  • When using the WHATWG parser, inspect the exception’s errors property for the precise reason.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified URL cannot have password

Description

The WHATWG URL Standard, implemented by the Uri\WhatWg\Url class introduced in PHP 8.5, forbids credentials and a port on file: URLs: a local file path has no notion of an authenticated remote host. Calling withPassword() on a URL whose scheme is file therefore throws instead of silently producing an invalid URL.

Example

<?php

use Uri\WhatWg\Url;

$url = new Url('file:///path/to/file');

$url = $url->withPassword('secret');

?>

Alternatives

  • Do not set a password on a file: URL.
  • Use a scheme that supports userinfo components, such as ftp or https, if credentials are actually needed.

In previous PHP versions, this error message used to be :ref:the-specified-url-cannot-have-username. In more recent PHP versions, this error message is now :ref:the-specified-url-cannot-have-port.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified URL cannot have port

Description

The WHATWG URL Standard, implemented by the Uri\WhatWg\Url class introduced in PHP 8.5, forbids credentials and a port on file: URLs: a local file path has no notion of a remote network endpoint. Calling withPort() on a URL whose scheme is file therefore throws instead of silently producing an invalid URL.

Example

<?php

use Uri\WhatWg\Url;

$url = new Url('file:///path/to/file');

$url = $url->withPort(8080);

?>

Alternatives

  • Do not set a port on a file: URL.
  • Use a scheme that supports a port component, such as http or ftp, if a network endpoint is actually needed.

In previous PHP versions, this error message used to be :ref:the-specified-url-cannot-have-password.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified URL cannot have username

Description

The WHATWG URL Standard, implemented by the Uri\WhatWg\Url class introduced in PHP 8.5, forbids credentials and a port on file: URLs: a local file path has no notion of an authenticated remote host. Calling withUsername() on a URL whose scheme is file therefore throws instead of silently producing an invalid URL.

Example

<?php

use Uri\WhatWg\Url;

$url = new Url('file:///path/to/file');

$url = $url->withUsername('root');

?>

Alternatives

  • Do not set a username on a file: URL.
  • Use a scheme that supports userinfo components, such as ftp or https, if credentials are actually needed.

In more recent PHP versions, this error message is now :ref:the-specified-url-cannot-have-password.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The specified userinfo is malformed

Description

The userinfo component of a URI may only contain unreserved characters, the sub-delimiters, :, and percent-encoded octets (RFC 3986, section 3.2.1). Uri\Rfc3986\Uri::withUserInfo() and Uri\Rfc3986\UriBuilder::setUserInfo() throw when the given string contains a character outside that set — here, the unencoded /.

Example

<?php

$uri = Uri\Rfc3986\Uri::parse('https://example.com');

$uri = $uri->withUserInfo('us/r:password');

?>

Alternatives

  • Percent-encode any reserved or non-ASCII character before passing it as userinfo.
  • Restrict userinfo to unreserved characters, sub-delimiters and :.

In previous PHP versions, this error message used to be :ref:cannot-set-a-userinfo-without-having-a-host. In more recent PHP versions, this error message is now :ref:failed-to-update-the-userinfo.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The SQLite3 object has not been correctly initialised or is already closed

Description

There was an attempt to use the Sqlite3 database, while it is not yet initialised, or already closed.

When extending the Sqlite3 class, make sure the constructor calls the parent constructor, so that Sqlite3 is actually initiliazed.

Note that the Sqlite3 object was not unset yet, so it still exists. It would have been another error then.

Example

<?php

// Not yet initialized object
$sqlite3 = new class (':memory:') extends Sqlite3 {
    function __construct() {}
};
$sqlite3->query('SELECT 1'); // OK

// already closed object
$sqlite3 = new Sqlite3(':memory:');
$sqlite3->query('SELECT 1'); // OK
$sqlite3->close();
$sqlite3->query('SELECT 1'); // Not OK

?>

Alternatives

  • Check that the parent class of an extended Sqlite3 class is actually called.
  • Check that the parent class was not already destroyed.
  • Check that whole object is destroyed, not just the parent class.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

The use statement with non-compound name '%s' has no effect

Description

This warning reports a useless use expression. The use expression imports the final name of a fully qualified name to be used in the current file. When applying use to a simple name, without any \ separator, PHP does not import it, as it is already treated as such by default.

Example

<?php

use Some\Space\Functions; // allow Functions to be used in this file
use Closure;              // Closure is already handled that way, no need to import it

function foo(Closure $closure) {}

?>

Alternatives

  • Remove the single name use expressions.
  • Fix the imported name to include a namespace, if applicable.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Too few arguments to function %s%s%s(), %d passed and %s %d expected

Description

This error reports that not enough parameters were used when calling a method or a function. All the arguments in the method signature are compulsory.

While there is an error message when there are missing arguments at call time, there is not error when too many arguments are provided.

Example

<?php

function foo($a, $b) {}

foo(1);

?>

Literal Examples

  • Too few arguments to function foo(), 1 passed and exactly 2 expected

Alternatives

  • Provide more arguments to the method call.
  • Add default values to the missing parameters in the method signature.

Too few arguments to function %s%s%s(), %d passed and %s %d

Description

This error reports that not enough parameters were used when calling a method or a function. A number of the arguments in the method signature are compulsory and at least that many argument must be provided.

Although parameters with default values should be all in the tail of the signature, it is still a valid, yet deprecated, feature. Then, using positional arguments, the code might yield this error as some of the positional arguments might fill some default parameters, leaving unsatisfied parameters later in the list.

While there is an error message when there are missing arguments at call time, there is not error when too many arguments are provided.

Example

<?php

function foo($a, $b, $c = 2) {}
foo(1);

// deprecated features: $c should be before $b, or get a default value, or $b might have no default value.
function bar($a, $b = 1, $c) {}
bar(1,2);
// Here, $c is not provided, 

?>

Literal Examples

  • Too few arguments to function foo(), 1 passed and exactly 2 expected

Alternatives

  • Use named parameters to assign arguments to the compulsory arguments.
  • Provide more arguments to the method call.
  • Add default values to the missing parameters in the method signature.

Too few arguments to function %s%s%s(), %d passed in %s on line %d and %s %d expected

Description

This error is emitted when the number of arguments to call a method or a function is not enough.

Without the required number of arguments at function call, the function cannot execute, as some variables would be missing.

This error covers situations where all the arguments are compulsory.

Example

<?php

function foo($a, $b) {}

foo(1);

?>

Literal Examples

  • Too few arguments to function foo(), 1 passed in file.php on line 5 and exactly 2 expected

Alternatives

  • Add the missing arguments.
  • Add default values to the missing arguments.

Too few arguments

Description

Functions such as printf() require at least one argument, the format. In that argument, the function will identify and require more arguments, passed after this first one. When there is not enough arguments for the first one, this error appears.

Not that extra arguments are ignored silently by PHP.

This applies to printf(), sprintf(), fprintf().

Example

<?php

printf('%s %s', 1);

?>

Literal Examples

  • printf(): Too few arguments

Alternatives

  • Check that the format (first argument), has only the required placeholders %s, %i…
  • Check that the printf() has enough arguments to match the format.

In more recent PHP versions, this error message is now :ref:%d-arguments-are-required,-%d.

Trait “%s” not found

Description

This error appears when a trait is mentioned in the conflict resolution expression, but the trait is not part of the class.

PHP takes into consideration all the traits, even if they are added later than the conflict class.

Example

<?php

class X  { 
    // C is not a used trait
    use A, B { C::d insteadof E;}

    // E is a used trait, even if is not in the use above.
    use E;
}
?>

Literal Examples

  • Trait “E” not found

Alternatives

  • Add the missing trait.
  • Remove the missing trait and its conflict resolution.

Trait %s used by %s is deprecated%S

Description

PHP 8.4 introduced the #[\Deprecated] attribute to flag functions, methods and class constants as deprecated. PHP 8.5 extends this to traits: a trait declared with #[\Deprecated] emits this deprecation notice as soon as another class use-s it, pinpointing the class doing the using.

The optional since and message arguments of the attribute are appended to the notice, for example “ since 1.0, use LoggerTrait instead“, to help locate a replacement.

Example

<?php

#[\Deprecated(message: 'use LoggerTrait instead', since: '1.0')]
trait DeprecatedLoggingTrait {
    public function log(string $message): void {
        echo $message, PHP_EOL;
    }
}

class Service {
    use DeprecatedLoggingTrait;
}

?>

Literal Examples

  • Trait DeprecatedLoggingTrait used by Service is deprecated since 1.0, use LoggerTrait instead

Alternatives

  • Stop using the deprecated trait and switch to the alternative mentioned in the deprecation message.
  • If you own the trait, keep the #[\Deprecated] attribute until the trait is actually removed, so callers get a clear migration path.

Trait method %s::%s has not been applied as %s::%s

Description

Two methods with the same name were imported with two distinct traits: PHP could not decide which one to use.

Example

<?php

trait T {
    public function foo() { return 3; }
}
trait U {
    public function foo() { return 2; }
}

class Bar {
    use T, U;
}

$x = new Bar();
var_dump($x->foo());

?>

Literal Examples

  • Trait method U::foo has not been applied as Bar::foo, because of collision with T::foo

Alternatives

  • Change the name of the method in one of the trait.
  • Add aliasing when importing the traits.
  • Only use one of the trait.
  • Make one trait use the other one.

Traits cannot have constants

Description

Constants int traits were added in PHP 8.2. Until then, they were not allowed: at compile time this error was yield.

Example

<?php

trait T {
    const X = 1;
}

echo T::X;

?>

Alternatives

  • Put the constant in the host class.
  • Put the constant in an interface.
  • Do not use the constant.
  • Move to PHP 8.2 or later.

In more recent PHP versions, this error message is now :ref:cannot-access-trait-constant-%s::%s-directly.

Trying to access array offset on %s

Description

Null, boolean (true and false), integers and floats are not valid with the array syntax. That syntax uses the square brackets with an index, appended after the value.

Often, such syntax is used on returned values, which may be an array, or false (or null) in case of error: most of the time it is a valid array, but sometimes, it is a scalar type. Such usage is now reported since PHP 8.3.

Example

<?php

echo null[1];
//Warning: Trying to access array offset on null


$true = true;
echo $true['a'];
//Warning: Trying to access array offset on true

$true = false;
echo $true[[33]]; // also, invalid idnex
//Warning: Trying to access array offset on false

?>

Literal Examples

  • Trying to access array offset on true
  • Trying to access array offset on false
  • Trying to access array offset on null

Alternatives

  • Check for types before using an array syntax on a returned value.
  • Initialize variables with an array, whenever it will be used with this type later.

Trying to clone an uncloneable object of class %s

Description

It is not possible to instantiate certain classes. This is the case of enumerations and generators.

It is also not possible to clone an enumeration cases, which are actually of the same type as the enumeration itself. The only usage is to access the cases of the enumeration: they are directly the expected objects.

On the other hand, it is possible to clone a closure.

Example

<?php

enum E {
    case A;
}
clone E::A;

$g = function () { yield 1; };
clone $g;

$c = function () { return 1; };
clone $c;

?>

Literal Examples

  • Trying to clone an uncloneable object of class e

Alternatives

  • Use the case E::A. Make sure it is not a class constant, which might be cloned.
  • For generator, call the original variable anytime the code needs a new source for a loop.

Trying to invoke %s method %s::%s() from scope %s

Description

This error reports that the requested method exists, but is not available from the context of call. Here, the method is protected and should only be called from a child class of x.

There are distinct messages for calling an unknown method, or calling a private method.

Example

<?php

class X {
    protected function foo() {}
}

class Y {
    function g() {
        $x = new X;
        $x->foo();
    }
}

(new Y)->g();

?>

Alternatives

  • Check the name of the method for typo.
  • Check the object of the method is the correct one.

Type %c: unknown format code

Description

pack() and unpack() convert data between a string representation and another. They both use a format string, passed as first argument, that specifies how the data of the second argument are transformed. This format string uses a limited set of letters (and @) to express these transformation. Any other character is not recognized and produces this error.

The valid characters are : a, A, h, H, c, C, s, S, n, v, i, I, l, L, N, V, q, Q, J, P, f, g, G, d, e, E, x, X, Z, @

The format is checked after collecting the parameters, and before attempting the transformation.

Example

<?php

$array = unpack("z", $someData);

?>

Literal Examples

  • Type z: unknown format code

Alternatives

  • Remove the unknown characters.
  • Fix the unknown character with a valid one.

Type %s cannot be part of an intersection type

Description

An intersection type, like string&Iterator, requires a value to be an instance of every listed type at once. That is only meaningful for class and interface names: a value can implement several interfaces simultaneously.

Scalar and compound pseudo-types (int, float, string, bool, array, callable, iterable, mixed, void, never, null, false, true), as well as self, parent and static, cannot be combined into an intersection, since nothing can be, for instance, a string and an object implementing Iterator at the same time.

Example

<?php

function foo(): string&Iterator {}

?>

Literal Examples

  • Type string cannot be part of an intersection type

Alternatives

  • Remove the scalar or pseudo-type from the intersection, and keep only class or interface names.
  • Use a union type (|) instead, if any of the alternatives is acceptable.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Type %s contains both iterable and array, which is redundant

Description

Since PHP 8.0 and the advent of union types, it is possible to write a type with duplicate type in it. This is obviously the case of the second function, in example.

It is less obvious to spot that array and iterable are redundant, yet, iterable = array|Traversable. So, iterable is sufficient, to also cover array.

This is a specific case of the general error that target any duplicate type in a definition.

Example

<?php

function foo() : array|iterable { }

function goo() : array|array { }

?>

Literal Examples

  • Type iterable|array contains both iterable and array, which is redundant

Alternatives

  • Remove the array type, and only use iterable for both.
  • Remove the iterable type, and only use array for this type.

In more recent PHP versions, this error message is now :ref:duplicate-type-%s-is-redundant.

Type %s contains both object and a class type

Description

The object type already matches an instance of any class. Adding a specific class name next to it in a union type, such as object|Test, does not widen what is accepted: every value that matches Test already matches object. PHP detects this redundancy purely from the type names, without needing Test to be defined or loaded.

The full message reads: Type %s contains both object and a class type, which is redundant.

Example

<?php

function test(): object|Test {
}

?>

Literal Examples

  • Type Test|object contains both object and a class type, which is redundant

Alternatives

  • Remove the specific class name, and keep only object.
  • Remove object, and keep only the specific class name, if that narrower type is what is actually intended.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Type %s is redundant as it is more restrictive than type %s

Description

DNF (Disjunctive Normal Form) types, added in PHP 8.2, allow an intersection group to be combined inside a union, as in (A&B)|C. If one of the union’s plain members already appears on its own, here A, then any intersection group built from that same name, such as A&B, cannot accept any value beyond what A alone already accepts: satisfying A&B always implies satisfying A.

PHP detects this purely by comparing the type names in the declaration, without loading any class, and rejects the more restrictive branch as dead code.

Example

<?php

interface A {}
interface B {}

function test(): (A&B)|A {}

?>

Literal Examples

  • Type A&B is redundant as it is more restrictive than type A

Alternatives

  • Remove the redundant intersection group, and keep only the broader standalone type.
  • If the intersection group was meant to be independent, use a type that is not already implied by one of the union’s other members.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Type %s is redundant with type %s

Description

In a DNF (Disjunctive Normal Form) type, two intersection groups can look textually different while describing the exact same combination of types once names are resolved. Here, B is only a local alias for A (introduced by use A as B;), so X&A and X&B are, in fact, the very same intersection written twice.

PHP resolves use aliases at compile time, notices that the second group adds nothing over the first, and reports it as redundant.

Example

<?php

interface X {}

use A as B;

function foo(): (X&A)|(X&B) {}

?>

Literal Examples

  • Type X&A is redundant with type X&A

Alternatives

  • Remove the duplicated intersection group.
  • Use the class’s real name consistently, instead of mixing the name and its alias.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Type contains both true and false, bool must be used instead

Description

PHP has several types. They may combined to provide the same type safety one another: PHP reports those situations, and prevents them.

Here, the bool type represents true|false. So, when both true and false are used in the type, they should be replaced with bool.

bool|true or bool|false yields another error; bool&true is not possible, at all.

Example

<?php

function foo() : int|true|false {}

?>

Alternatives

  • Use the bool type instead.
  • Remove the usage of either true or false, or both.

Type declaration ‘%s’ must be unqualified

Description

Scalar types are absolute, and shall not be written with the initial \. It is always omitted.

This error is reported for string, int, bool, iterable, never, void, object, float, null, mixed, true, false.

For some reason, array and callable are still not reported with this error. resource is also ignored, although it is only reserved, and not supported anyway.

Example

<?php

    function foo(\string $x) {}

?>

Literal Examples

  • Type declaration ‘array’ must be unqualified
  • Type declaration ‘string’ must be unqualified
  • Type declaration ‘int’ must be unqualified
  • Type declaration ‘null’ must be unqualified

Alternatives

  • Remove the leading backslash.
  • Remove the whole type.
  • Use a class type, which supports the leading backslash.

Type mixed can only be used as a standalone type

Description

mixed is a special type, that represents all the available types. There is no need to combine this type in an union, as all the types are already compiled in mixed; Nor it can be combined in an intersectional type.

Example

<?php

function foo(A|mixed $i = null) {}

?>

Alternatives

  • Remove the mixed type and use other types.
  • Remove the mixed type entirely.

Type mixed cannot be marked as nullable since mixed already includes null

Description

mixed is a special type, that represents all the available types, include null.

Example

<?php

function foo(?mixed $i = null) {}

?>

Alternatives

  • Remove the ? type with mixed.
  • Keep the ? type, and replace mixed, with some other type.

Type must be a single character

Description

The type argument of the snmp2_set() function is a list of types: one or more. Each type must a string of a single character, no more, no less.

The allowed values are : ‘=’, ‘i’, ‘u’, ‘s’, ‘x’, ‘d’, ‘n’, ‘o’, ‘t’, ‘a’, ‘b’, ‘U’, ‘I’, ‘F’, ‘D’.

Example

<?php

    $z = snmp2_set(hostname: $hostname, 
                   community: $communityWrite, 
                   object_id: array($oid1, $oid2), 
                   type: array('s','sb'), 
                   value: array($newvalue1, $newvalue2), 
                   );

?>

Alternatives

  • Remove any invalid type.
  • Remove types that are more than one character.
  • Remove types that are less than one character.

Type of %s::$%s must be %s%s (as in class %s)

Description

Property definitions must be compatible one another, between a parent and a child class. With this error message, the parent class defined a type for the property, and so, the child class should also define it. On the other hand, it may change the default value.

Example

<?php

class X {
    public $a;
}

class Y extends X {
    public array $a;
}

?>

Literal Examples

  • Type of X::$a must be array (as in class Y)

Alternatives

  • Use the type to the child class in the parent, and the sibling classes.
  • Use the type of the parent class.

Type of %s::$%s must be omitted to match the parent definition in class %s

Description

A property cannot be redefined, by adding the mixed type to it. It looks like untyped property and mixed type property should behave the same, but they are not: in particular, typed properties have an ‘uninitialized’ state, which yields fatal errors when the property is read, which does not apply to untyped properties.

Example

<?php

class Foo
{
    public $property;
}

class Bar extends Foo
{
    public mixed $property;
}

?>

Literal Examples

  • Type of X::$p must be omitted to match the parent definition in class X

Alternatives

  • Add the mixed type to the parent property definition.
  • Remove the mixed type from the child property definition.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Type of %s::$%s must not be defined (as in class %s)

Description

Property definitions must be compatible one another, between a parent and a child class. With this error message, the parent class did not define a type for the property, and so, the child class should also not define it. On the other hand, it may change the default value.

Example

<?php

class X {
    public $a;
}

class Y extends X {
    public array $a;
}

?>

Literal Examples

  • Type of Y::$a must not be defined (as in class X)

Alternatives

  • Add the type to the parent class, and the sibling classes.
  • Remove the type in the child class.

Type of %s::%s must be compatible with %s::%s of type %s

Description

PHP 8.3 introduced typed class constants: a class constant may declare the type of value it holds, and that type is enforced. When a class overrides a typed constant inherited from a parent class or an implemented interface, the overriding constant’s type must be covariant with the parent’s, meaning it must be the same type, or a subtype of it, never a wider or unrelated one.

Here, Colorful::COLOR is typed string, but Item redeclares it as int, which is not a subtype of string. Since callers relying on Colorful::COLOR expect a string, PHP rejects the mismatch at compile time.

Example

<?php

interface Colorful {
    const string COLOR = 'unknown';
}

class Item implements Colorful {
    const int COLOR = 1;
}

?>

Literal Examples

  • Type of Item::COLOR must be compatible with Colorful::COLOR of type string

Alternatives

  • Use the same type as the parent constant, or a subtype of it.
  • Remove the type declaration from the child constant’s declaration, if the language version allows omitting it.
  • Rename the constant, if it is not meant to override the parent one.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Type of parameter $%s of hook %s::$%s::set must be compatible with property type

Description

When a set hook declares an explicit parameter type, that type is what callers of $object->prop = $value are constrained to. Because the hook is the only way to write to the property, its parameter type must be able to accept every value that the property’s own declared type allows; it must be the same as, or wider (contravariant) than, the property type, never narrower.

In the example, $prop is declared as string|array, but the set hook only accepts string. An assignment of an array would satisfy the property’s declared type but be rejected by the hook’s parameter type, which PHP considers an incompatible, and therefore invalid, declaration.

The same error occurs when the property itself has no explicit type (implicitly mixed) but the set hook restricts its parameter to a specific type, since mixed is wider than any concrete type.

Example

<?php

class Test {
    public string|array $prop {
        set(string $prop) {}
    }
}

?>

Literal Examples

  • Type of parameter $prop of hook Test::$prop::set must be compatible with property type

Alternatives

  • Widen the set hook’s parameter type so that it accepts everything the property’s declared type allows, e.g. change set(string $prop) to set(string|array $prop).
  • Remove the explicit type from the set hook’s parameter, letting it default to the property’s type.
  • Narrow the property’s declared type to match what the set hook is willing to accept.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Typed property %pS::$%pS must not be accessed before initialization

Description

Typed properties are undefined until they are assigned for the first time, either through a default value or by an explicit assignment. This differs from untyped properties, where reading before assignment simply yields NULL: because a typed property must always hold a value matching its declared type, and NULL is not a valid value unless the type is nullable, PHP raises an error instead of inventing one.

The coalesce ??, isset() and empty() operators can be used to check whether the property has been initialized, even though it is not set. Be careful not to confuse an uninitialized property with one that is merely empty.

Example

<?php

class X {
    public int $property;
}

$x = new X;
echo $x->property;

?>

Literal Examples

  • Typed property X::$property must not be accessed before initialization

Alternatives

  • Give the property a default value.
  • Avoid calling unset() on typed properties, as it resets them to the uninitialized state.
  • Assign the property in the constructor.
  • Use isset(), empty() or ?? to check the property’s status before reading it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Typed property %s::$%s must not be accessed before initialization

Description

Typed properties are undefined until they are assigned for the first time. Such happens with a default value, or at the first assignation.

The difference with untyped values, is that PHP emits that error when the property is not typed. On the other hand, an undefined property gets a NULL value instead.

The coalesce ??, isset() and empty() operators may be used to check if the property exists, even when it is not defined. Be careful to avoid confusing an undefined property and its empty equivalent.

Example

<?php

    class X {
    	public int $property;
    }
    
    $x = new X;
    echo $x->p;

?>

Literal Examples

  • Typed property x::$p must not be accessed before initialization

Alternatives

  • Give a default value to the property.
  • Remove usage of unset() on properties, as they are then reset to uninitialized state.
  • Set the value of the property in the constructor.
  • Use isset(), empty() or ?? to check the status of the property before usage.

Typed static property %s::$%s must not be accessed before initialization

Description

Typed static properties are undefined until they are assigned for the first time. Such happens with a default value, or at the first assignation.

The difference with untyped values, is that PHP emits that error when the property is not typed. On the other hand, an undefined property gets a NULL value instead.

The coalesce ??, isset() and empty() operators may be used to check if the property exists, even when it is not defined. Be careful to avoid confusing an undefined property and its empty equivalent.

Example

<?php

class X {
	public static int $property;
}

echo x::$property;

?>

Literal Examples

  • Typed static property x::$p must not be accessed before initialization

Alternatives

  • Give a default value to the property.
  • Set the value of the property in the constructor.
  • Use isset(), empty() or ?? to check the status of the property before usage.

Unable to generate salt

Description

password_hash() creates a random salt for each hash, using random bytes from the operating system. If those bytes cannot be read, no salt can be made, so no hash is produced and this error is thrown.

This is an environment problem rather than a problem in the code that calls password_hash(). It is rare, and it is usually reported on systems where the random source is not available to PHP, or where entropy is missing, such as some containers and virtual machines.

Example


Literal Examples

  • Unable to generate salt

Alternatives

  • Check that random_bytes() works on the system, for example by calling random_bytes(16) in a small script.
  • Check the random source of the operating system and of the container or virtual machine, and make sure PHP can read from it.
  • Check the PHP build and its extensions, as a broken build can also lead to this error.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unbacked enum %s cannot be converted to a string

Description

http_build_query() function convert an array of strings to their URL encoded version. When encountering an enumeration, it makes it work with string and integer enumerations, but not with the unbacked enumerations.

Example

<?php

enum E {
    case A;
}

try {
    echo http_build_query(['e' => E::A]);
} catch (ValueError $e) {
    echo $e->getMessage(), \n;
}

?>

Alternatives

  • Add a type to the enumeration, string or int. Then, add values to the cases.
  • Convert the enumeration cases into strings before using them with http_build_query().

Unclosed '(' does not match ']'

Description

This is a variation of the unbalanced parenthesis or square brackets. Here, the parenthesis were not closed before the nesting square brackets was closed.

Example

<?php

$array[foo(1,2]; 

?>

Alternatives

  • Close the parenthesis before closing the square bracket.

Unclosed '(' on line %s does not match ']'

Description

PHP keeps track of parenthesiss and square brackets. Any of them that is opened, must be closed by the corresponding one. In the current situation, an open parenthesiss is followed by a closing square bracket, which does not match.

Example

<?php

$array = [foo(1, 2];

?>

Literal Examples

  • Unclosed ‘(’ on line 17 does not match ‘]’

Alternatives

  • Close the parenthesis before the closing square bracket.
  • Open a square bracket after the opening parenthesis.

Unclosed ‘(’

Description

The closing parenthesis is missing.

It might be missing, as in the first two examples; it might also be inside a string, as in the third example: the double quote is not closed, which includes the closing square bracket, and makes it missing.

Example

<?php

// These should be at the end of a code, without ; not ?>
foo($b, 3
$a = 10 * (2 + 3

// closing parenthesis is in the double quoted string
$b = 'c' . ( "d . $e)

?>

Alternatives

  • Check that the square brackets are balanced.
  • Check that the closing square brackets are not hidden in a string.

Unclosed ‘[’

Description

The closing square bracket is missing.

It might be missing, as in the first example; it might also be inside a string, as in the second example: the double quote is not closed, which includes the closing square bracket, and makes it missing.

Example

<?php

// This should be at the end of a code, without ; not ?>
$a[$b[3] 

$a["3] = 4;

?>

Alternatives

  • Check that the square brackets are balanced.
  • Check that the closing square brackets are not hidden in a string.

Unclosed ‘{’

Description

The most frequent situation is an unbalanced block: blocks are delimited with curly brackets, and there must be the same number of opening and closing. In this case, one (at least) too many opening is missing its closing bracket.

Alternatively, both brackets are apparently available, but one of them is in a string: see the last entry, where a double-quoted string was started, but never finished. The whole code, after the double-quote, is now in a string, and PHP discarded the closing bracket as a literal, not a token.

This error may related to the PHP short tags. In the heart of the B method, the PHP tag is closed, then opened again. That second opening is using the PHP short tags. When this directive is disabled, it makes the rest of the text after the closing tag literal, and it is not parsed anymore into PHP code. Since the closing brackets are there, PHP reports they are missing.

Example

<?php

{ $a = 1+2; 

class A
{
	public function B()
	{
		?>C<?
	}

}

// bracket is buried in the string
{ $b = "1+2; }

?>

Alternatives

  • Make the short open tag a full <?php.
  • Activate the short open tag directive <?php.
  • Check that double quotes are all balanced.
  • Check that curly brackets are all balanced.

Undefined array key

Description

This notice is emitted when an offset (string or integer) is being used before being defined. In a word, the element at this offset does not exist, so PHP creates it on the fly, as NULL, then uses it.

Example

<?php

// undefined array key 4
echo [1,2,3][4];

// undefined array key 'a'
echo [1,2,3]['a'];

// undefined array key 1
list($a, $b) = ['c'];

?>

Alternatives

  • Test the existence of the offset before usage.
  • Gives the offset a default value before usage.
  • Check that the right operand of a list() call has enough elements to fit the left operand.

In previous PHP versions, this error message used to be :ref:undefined-offset.

Undefined class constant ‘%s::%s’

Description

The requested class constant doesn’t exist.

In the case of an enumeration, this error message is also displayed for the cases: they do have the same syntax, so it is not possible to know if it is a constant or a case.

Example

<?php

class X {}

echo X::Y; 

enum E { case A;}

echo E::B;

?>

Literal Examples

  • Undefined class constant ‘x::Y’
  • Undefined class constant ‘e::B’

Alternatives

  • Find the actual name of the requested class constant.
  • Find the actual class of the requested class constant.
  • Define the class constant in the class, or its traits, interfaces or parents.

In more recent PHP versions, this error message is now :ref:undefined-constant-%s::%s.

Undefined constant “%s”

Description

The requested constant doesn’t exist.

The constant may be defined at different places in the code :

  • In the running code: it could be in a different file, which was not included yet, or later in the code.
  • In a dependency: use the name of the constant to find which dependency defines this constant. Then, make sure the dependency is satisfied.
  • In an extension: use the name of the constant to find which PHP extension defines this constant. For example, XML_PI_NODE is from the ext/xml extension, which may not be in the current PHP engine.

There is a distinct message for class constants.

It is possible to create a circular definition of constant, that leads to this error message. This is the case with a direct recursive definition, where the constant is used to define itself. Since the constant is not defined yet, it cannot be used in the right expression, and that leads to an ‘undefined constant’ error.

It is also possible to build such recursive structure by using an object, and using that constant in the class of the related object.

Example

<?php

// early usage of the constant
echo A;

const A = 2;

// Recursive constant definition
const A = A + 1;

// Recursive constant definition (longer version)
class X {
    const B = C;
}
const C = new X;

?>

Literal Examples

  • Undefined constant “A”
  • Undefined constant “XML_PI_NODE”

Alternatives

  • Find the actual name of the requested constant.
  • Check the namespace, or its import: use const.
  • Check if the constant is used after its definition.
  • Check if the constant is defined in a PHP extension, and the extension was forgotten.
  • Check if the constant is defined in a dependency, and the dependency was forgotten.

Undefined constant %s::%s

Description

The requested class constant could not be found.

The error message is distinct for the global constants, although there is no mention of class in this one.

Example

<?php

class X {
	const Z = 1;
	private A = 2;
}

echo X::Y; 

?>

Literal Examples

  • Undefined constant X::CONSTANT

Alternatives

  • Find the actual name of the requested class constant.
  • Find the actual class of the requested class constant.
  • Check the namespace, or its import.
  • Check the visibility of the class constant: it may be private, or protected.
  • Check the autoload system, to make sure the definition could be found.
  • Define the class constant in the class, or its traits, interfaces or parents.

In previous PHP versions, this error message used to be :ref:undefined-class-constant-'%s::%s'.

Undefined global variable %s

Description

$GLOBALS is a superglobal that stores all the defined global variables. It yields this warning when trying to reach a global via one of its index.

Example

<?php

function foo() {
    echo $GLOBALS['a']; 
}

foo();

?>

Literal Examples

  • Undefined global variable $a
  • Undefined global variable $GLOBALS

Alternatives

  • Create the global with the global keyword before accessing it.

Undefined offset

Description

This notice is emitted when an offset (string or integer) is being used before being defined. In a word, the elemenent at this offset is not created yet, so PHP creates it on the fly, as NULL, then uses it.

Example

<?php

echo [1,2,3][4];

?>

Alternatives

  • Test the existence of the offset before usage.
  • Gives the offset a default value before usage.

In more recent PHP versions, this error message is now :ref:undefined-array-key.

Undefined property %s::$%s

Description

This error is reported when reading an undefined property. The property must be defined before usage, or, in older PHP versions, the property must have been assigned.

This error is related to properties: a different error is emitted for static properties.

Example

<?php

class X {
	public $a = 1;
}

$x = new X;
echo $x->a;
echo $x->b;

?>

Literal Examples

  • Undefined property x::$b

Alternatives

  • Define the property before using it.
  • Fix the name of the property, and replace it with an existing one.
  • Define the magic property method __get() to make any property available.

Undefined variable $%S

Description

This error appears when a variable is used, aka read, while it was not defined before.

This might be a variable passed by argument to a method; a variable used with a short assignation operator or an argument of the PHP native function compact.

Example

<?php

$x += 1;

foo($a);

compact('undefined');

function foo($a) {}

?>

Alternatives

  • Use another variable.
  • Check the variable before usage.
  • Give a default value to the variable before usage.

Undefined variable

Description

This notice is emitted when a variable is being used before being defined. In a word, the variable is not created yet, so PHP creates it on the fly, as NULL, then uses it.

The situation arises when reading a variable, such as the echo call here. It doesn’t happen upon writing, as it is the way to make a variable definition.

It also happens when using the compact native function: it collects the values of variables into an array, and emits this error whenever the variable doesn’t exist. The entry is also skipped in the result.

The error may be related to a PHP defined variable, which is not available due to version or context. For example, $phperrormsg was removed in PHP 8.0, and $_GET is not available in command line context, aka, without a web server.

Example

<?php

echo $x;

compact('a');

?>

Alternatives

  • Give the variable a default value.
  • Check if the version supports the PHP defined variable.
  • Check if the context supports the variable: web or command line.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See compactThrowsNotice

Unexpected character in input: '\’ (ASCII=92)

Description

This linting error appears at linting time, until PHP introduced namespaces, whose separator is \. Then, it was added to the recognized characters.

Example

<?php

    use \A\B as C;

?>

Alternatives

  • Upgrade to PHP 5.3 or later.
  • Replace the backslash by an underscore.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

unexpected NAN value was coerced to %s

Description

When a NAN (Not a Number) float value is coerced to another type such as int or string, PHP emits this warning. NAN is a special float value that represents an undefined or unrepresentable result of a floating-point operation.

Coercing NAN to int produces 0, and coercing it to string produces an empty string. These results are misleading since NAN is not equivalent to zero or empty. The warning alerts developers that a NAN value is silently converted, which is almost certainly unintended.

NAN is produced by operations like acos(8), log(-1), sqrt(-1), or 0.0/0.0.

Example

<?php

// NAN coerced to int
$a = (int) NAN;
// $a = 0

// NAN coerced to string
$b = (string) NAN;
// $b = "" 

// NAN passed to an integer parameter
function foo(int $x) {} 
foo(NAN);

?>

Literal Examples

  • unexpected NAN value was coerced to int
  • unexpected NAN value was coerced to string

Alternatives

  • Check for is_nan() before coercing or passing the value to a typed parameter.
  • Handle NAN explicitly at its source by validating the result of math operations.
  • Use is_finite() to filter out both NAN and INF before using a float value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unhandled match case %s

Description

The error is emitted when the matching value is not found in the list of entry of the expression (here true is not in the list of 1 and 2), and also when the expression doesn’t have a default entry. That default entry would act as a catch-all entry, and would process unknown values.

Example

<?php

match(3) {
    1, 2 => 'foo',
};

?>

Literal Examples

  • Unhandled match case 3

Alternatives

  • Add the missing entry in the list.
  • Add the missing default in the match.
  • Weed out the value before submitting it to the match().

Uninitialized string offset

Description

This error appears when using the array syntax on strings, while the requested index is too large, or too small.

An offset is too big when it is beyond the length of the string. An offset is too small with it is below the length of the string, multiplied by -1. All values between - strlen($string) and strlen($string) are valid.

This error is displayed when the string offset is read. It becomes a Illegal string offset when the syntax is used to write a character.

Example

<?php

$string = 'abc';

//Uninitialized string offset
echo $string[-10];

//Uninitialized string offset that is too big
echo $string[5];

?>

Literal Examples

  • Uninitialized string offset 1
  • Uninitialized string offset 5
  • Uninitialized string offset -5

Alternatives

  • Check for the size of the string before using the offset.
  • Use substr(), which returns empty string for out of range offsets.

Unknown digest algorithm: %s

Description

The digest algorithm name passed to a hash function is not recognized by PHP’s Hash extension.

The hash(), hash_file(), and hash_hmac() functions rely on a registry of supported algorithms. When an algorithm name is not found in that registry, this warning is emitted and the function returns false.

The list of available algorithms depends on the extensions loaded at runtime. Algorithms may be added or removed depending on the PHP version and compiled extensions.

Algorithms are case-insensitive, but misspellings will still produce this error.

Example

<?php

// hash() with a valid algorithm works
hash('sha256', 'my data');

// hash() with an unknown algorithm triggers the warning
hash('unknown_algo', 'my data');

// hash_file() also triggers it
hash_file('bad_algo', '/tmp/file.txt');

// hash_hmac() too
hash_hmac('invalid', 'my data', 'secret');

?>

Literal Examples

  • Unknown digest algorithm: blowfish
  • Unknown digest algorithm: tiger
  • Unknown digest algorithm: sha3-224

Alternatives

  • Check available algorithms with hash_algos() before using one.
  • Use one of the standard algorithms: md5, sha1, sha256, sha512, sha3-256.
  • Verify the algorithm is available by checking in_array($algo, hash_algos()).
  • Install or enable the required extension that provides the algorithm (e.g. hash with GOST support).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unknown filter with ID

Description

filter_var_array(), and other filter functions, use the second argument to identify which filter to apply. They are usually provided as constants, such as FILTER_SANITIZE_STRING. There are a limited, although long, set of such constants, and not all integer values are used. This is the case for -1.

Example

<?php

var_dump(filter_var_array(array(=>), 128));

?>

Literal Examples

  • Unknown filter with ID -1
  • Unknown filter with ID 128

Alternatives

  • Use a valid constant to specify the filter.
  • Do not use literal integers, but constants.

Unknown format specifier “%c

Description

printf() accepts a string of formats, as the first arguments. A format is a % character, followed by a letter. Some letters are not allowed: a, i, j, k, l, m, n, p, q, r, t, v, w, y, z, A, B, C, D, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, Y, Z.

Example

<?php

    printf(\%we3e\, 123); 
    //Unknown format specifier \w\

?>

Alternatives

  • Replace the reported letter with a valid format letter.
  • Duplicate the % sign, to make it literal.

Unknown hook “%s” for property %s::$%s, expected “get” or “set”

Description

Property hooks can only be named ‘get’ or ‘set’, as of PHP 8.4. In the future, there may be new ones, but not in that version. Also, case is not important.

Example

<?php

class X
{
    public string $property {
        got {
            $this->name = $value;
        }
    }
}

?>

Literal Examples

  • Unknown hook “got” for property X::$property, expected “get” or “set”

Alternatives

  • Use ‘set’ or ‘get’ as the name of the hook.
  • Wait for a future version of PHP.

Unknown hook "%s" for property %s::$%s

Description

There can be only two property hooks: get and set, and their case variations. All others are currently explicitly forbidden.

Example

<?php

class Test {
    public $prop {
        foobar {}
    }
}

?>

Literal Examples

  • Unknown hook “foobar” for property Test::$prop

Alternatives

  • Use one of the valid names.
  • Remove the property hook.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unknown named parameter $%s

Description

Named parameters are the parameters of the function, or method. Their actual name is the name of the variable, without the leading $ sign.

With named parameters, the case is important, just like with variables.

Example

<?php

    function foo($a, $b) {}

    foo(c: 1);

?>

Literal Examples

  • Unknown named parameter $c

Alternatives

  • Check the case of the parameter.
  • Check the signature of the method to see if that parameter actually exists.
  • Add the parameter to the method signature.
  • Remove the name in the method call, and rely on positional arguments.
  • Check the actual method definition: interfaces have precedence, then in the class hierarchy, it is the last defined method, in class or trait.

Unknown or bad format (%s)

Description

This error is emitted by the Date extension, when creating a DatePeriod class. That class requires a start date as the first argument, and the provided value could not be parsed.

Example

<?php

new DatePeriod('L');

?>

Literal Examples

  • Unknown or bad format (L)

Alternatives

  • Use a valid date.
  • Use a DateTimeInterface object as first argument: DateTimeImmutable, DateTime, etc.
  • Use the DatePeriod::createFromISO8601String() method to handle ISO 8601 formats.

Unknown parser

Description

This is an internal error, raised during testing. It relates to the URI class, and the available parsers.

Example


Alternatives

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

unlink of “%s” failed, file does not exist

Description

PHP reports failure when trying to remove a file that does not exists in a phar archive. This error message does not appear when using the regular filesystem, or the delete method on a phar object.

This error message is part of the stream system.

Example

<?php

try {
    $phar = new Phar('/tmp/myphar.phar');
    $phar->addFromString('foo.txt', 'hello');
    unset($phar);

    $phar = new Phar('/tmp/myphar.phar');
    unlink('phar:///tmp/myphar.phar/oops');
} catch (Exception $e) {
    // handle errors
    print $e->getMessage();
}
?>

Literal Examples

  • unlink of “oops” failed, file does not exist

Alternatives

  • Check if the file is available before removing it, with Phar::offsetExists.

Unmatched ‘)’

Description

PHP has encountered a closing parenthesis, but has no related opening parenthesis.

In more complex situations, there might be opening and closing parenthesis: this error reports that there are more closing ones than opening. Eventually, some will not have a matching bracket.

Inside double-quoted strings, the unmatched closing brackets are ignored, and used as literal value.

Example

<?php

$a = 1 + 2)

// One too many parenthesis
if (in_array(foo(), array()))) { doSomething(); }

?>

Alternatives

  • Remove the closing curly bracket.
  • Add an opening closing curly bracket.

Unmatched ‘]’

Description

PHP has encountered a closing parenthesis, but has no related opening parenthesis.

In more complex situations, there might be opening and closing parenthesis: this error reports that there are more closing ones than opening. Eventually, some will not have a matching bracket.

Inside double-quoted strings, the unmatched closing brackets are ignored, and used as literal value.

Example

<?php

$a[1 + 2 = 3;

// One too many parenthesis
if (in_array(foo(), array()))) { doSomething(); }

?>

Alternatives

  • Remove the closing curly bracket.
  • Add an opening closing curly bracket.

Unmatched ‘}’

Description

PHP has encountered a closing curly brackets, but has no related opening curly bracket.

In more complex situations, there might be opening and closing brackets: this error reports that there are more closing ones than opening. Eventually, some will not have a matching bracket.

Inside double-quoted strings, the unmatched closing brackets are ignored, and used as literal value.

Example

<?php

$a = 1 + 2}

// 3 opening, 4 closing. 
{{{$b = 1 + 2}}}}

// this unmatched closing bracket is taken as literal
$b = "$a} = 1+2"; 

?>

Alternatives

  • Remove the closing curly bracket.
  • Add an opening closing curly bracket.

Unparenthesized a ? b : c ? d : e is not supported.

Description

The nested ternary operator requires a clear definition of priorities, by using parenthesis.

The code above could be understood as ($a ? $b : $c) ? $d : $e or $a ? $b : ($c ? $d : $e). Until PHP 8.0, the engine choose the second option; Since then, it must be explicitly written.

Note that, in the error message, the letters represent a full expression. They may be variables, as in the illustration, but any other expression.

Example

<?php

$x = $a ? $b : $c ? $d : $e;

?>

Alternatives

  • Write the expression as ($a ? $b : $c) ? $d : $e.
  • Write the expression as $a ? $b : ($c ? $d : $e).
  • Rewrite the expression as an if/then.

Unparenthesized a ? b : c ?: d is not supported.

Description

Mixing a full ternary with the short ternary operator (?:) requires a clear definition of priorities, by using parenthesis.

The code above could be understood as ($a ? $b : $c) ?: $d or $a ? $b : ($c ?: $d). Until PHP 8.0, the engine chose the first option, since the ternary operator was left-associative; since then, it must be explicitly written.

Note that, in the error message, the letters represent a full expression. They may be variables, as in the illustration, but any other expression.

Example

<?php

$x = $a ? $b : $c ?: $d;

?>

Alternatives

  • Write the expression as ($a ? $b : $c) ?: $d.
  • Write the expression as $a ? $b : ($c ?: $d).
  • Rewrite the expression as an if/then.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unparenthesized a ?: b ? c : d is not supported.

Description

Mixing the short ternary operator (?:) with a full ternary requires a clear definition of priorities, by using parenthesis.

The code above could be understood as ($a ?: $b) ? $c : $d or $a ?: ($b ? $c : $d). Until PHP 8.0, the engine chose the first option, since the ternary operator was left-associative; since then, it must be explicitly written.

Note that, in the error message, the letters represent a full expression. They may be variables, as in the illustration, but any other expression.

Example

<?php

$x = $a ?: $b ? $c : $d;

?>

Alternatives

  • Write the expression as ($a ?: $b) ? $c : $d.
  • Write the expression as $a ?: ($b ? $c : $d).
  • Rewrite the expression as an if/then.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unserialization of %s is not allowed, override __serialize() and __unserialize() to implement it

Description

This is the mirror error of the serialization one. Some internal classes hold state, such as a connection handle or a resource, that cannot be meaningfully rebuilt from a plain serialized string. Unless the class implements __serialize() and __unserialize() (available since PHP 7.4) to define its own restoration logic, unserialize() refuses to instantiate the object from serialized data and throws this exception instead of returning a half-built, unusable instance.

Example

<?php

$serialized = 'O:3:PDO:0:{}';

$pdo = unserialize($serialized);

?>

Literal Examples

  • Unserialization of PDO is not allowed, override __serialize() and __unserialize() to implement it

Alternatives

  • Create a subclass that implements __serialize() and __unserialize() to control exactly how the object is restored.
  • Do not serialize instances of this class in the first place; persist the data needed to recreate it and rebuild the object manually.

In previous PHP versions, this error message used to be :ref:serialization-of-%s-is-not-allowed,-override-__serialize()-and-__unserialize()-to-implement-it.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unserializing the ‘S’ format is deprecated

Description

When using the unserialize() function, the string should not use S (upper case S) to format a string. It should only use s (lower case S).

Other formats, such as i, b or N are already case sensitive.

Example

<?php

$encoded = 'S:3:"abc";';

unserialize($encoded);

?>

Alternatives

  • Turn the S into lower case s. This might be tricky.
  • Serialize all over the stored strings with lower case.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See unserialize_S

Unsupported declare '%s'

Description

declare sets some directives for the file or block. The possible directives are limited to three: strict_types, the most common, ticks and encoding.

Example

<?php

declare(a = 1);

?>

Alternatives

  • Use one of the three valid declare directives.
  • Remove the declare call.

Unsupported operand types

Description

This error is emitted when PHP cannot find a reasonable way to use the parameters of an operator.

In the code example, the string ‘a4.4a’ cannot be converted to an integer or a float. This yield the error.

PHP could do with ‘4.4a’ (cast to 4.4 and a warning), or with ‘4.4’ (cast to a float silently).

On the other hand, the ‘a4.4a’ string cannot be converted to a numeric and it yields the error. Other types, such as an array, an object or a resource would yield the same error. Boolean and null are converted to integers.

This error applies to all operators, with matching constraints.

Conversion to string my be automatically happening, when the strict_type directive is not active.

The error is reported for the first or the second argument. It may also applies to both, though PHP stops at the first one it finds.

Example

<?php

echo a4.4a ** 4;

?>

Alternatives

  • Use an explicit cast to ensure the correct type of the operand.
  • Check the value before using it with the operator.

Unsupported operand types: %s %s %s

Description

This error is reported when the types of the operands are valid (here, int and string), but they are not compatible one another. It is possible to use the & operator with two integers, or with two strings but not with one string and one integer.

Example

<?php

1 & 'B'; 

?>

Literal Examples

  • Unsupported operand types: int & string

Alternatives

  • Make both sides of the operator the same type.

Unterminated comment starting line %

Description

Multi-line comments, written with /* ... */ or /** ... */, require a closing tag. When that closing tag is missing before the end of the file, PHP cannot determine where the comment was meant to stop and raises a compile error.

This problem does not affect single-line comments (// or #), since those are automatically closed by the end of the line.

Example

<?php

/*
comment

    Missing final / below
*

?>

Literal Examples

  • Unterminated comment starting line 3

Alternatives

  • Check that the closing tag is complete, with both * and /.
  • Check that a closing tag has not been omitted entirely.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Unterminated comment starting line %d

Description

The multi-line comments with /* ... */ and /** ... */ require a closing tag. When that closing tag is missing, the error is emitted.

This problem does not occur with the single line comment //, as this comment only ends with the end of the line.

Example

<?php

/*
comment

    Missing final / below
*        

?>

Literal Examples

  • Unterminated comment starting line 3

Alternatives

  • Check if the closing tag is complete, with * and /.
  • Check if the closing tag is not missing entirely.

Usage of ldap_connect with two arguments is deprecated

Description

ldap_connect() used to accept a hostname and a port as two separate arguments. Passing them separately does not let the caller express whether the connection should use ldap:// or ldaps://, or list several servers at once, which a single LDAP URI can do naturally.

Calling ldap_connect() with a separate hostname and port is now deprecated in favor of passing a single LDAP URI.

Example

<?php

$ldap = ldap_connect('ldap.example.com', 389);

?>

Alternatives

  • Pass a single LDAP URI instead, for example ldap_connect('ldap://ldap.example.com:389') or ldap_connect('ldaps://ldap.example.com').

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Usage of session.referer_check INI setting is deprecated

Description

session.referer_check makes session_start() check that the Referer HTTP header sent by the client starts with a given substring, rejecting the session otherwise. This mechanism dates back to a time when it was considered a lightweight session-hijacking mitigation, but the Referer header is client-supplied and trivially spoofed, so it provides no real security guarantee.

As part of the deprecation of PHP’s automatic, URL-based session ID propagation (also affecting session.use_trans_sid and related directives), setting session.referer_check to a non-empty value is deprecated as of PHP 8.4.0.

Example

<?php

ini_set('session.referer_check', 'example.com');

?>

Alternatives

  • Remove session.referer_check from php.ini and from the code; do not rely on the Referer header for session security.
  • Use proper session security measures instead, such as regenerating the session ID on privilege change and binding sessions to other verified signals.

Usage of session.trans_sid_hosts INI setting is deprecated

Description

session.trans_sid_hosts restricts on which hosts PHP is allowed to rewrite URLs to inject the session ID (trans sid), which only matters when session.use_trans_sid is enabled in the first place. Trans sid itself – propagating the session ID through the URL and hidden form fields instead of only a cookie – is a legacy mechanism being phased out because it leaks session IDs into logs, the Referer header, and shared/bookmarked links.

As of PHP 8.4, setting session.trans_sid_hosts to any non-empty value emits this deprecation notice, as part of a broader deprecation of GET/POST (URL-based) session propagation ahead of its removal in PHP 9.0.

Example

<?php

// A non-empty value (the empty-string default is fine) triggers the
// deprecation as soon as it's applied.
ini_set('session.trans_sid_hosts', 'example.com');

?>

Literal Examples

  • ini_set(): Usage of session.trans_sid_hosts INI setting is deprecated

Alternatives

  • Leave session.trans_sid_hosts empty and keep session.use_trans_sid disabled (its default), relying on cookies only.
  • If trans sid is still required for a specific legacy integration, treat the whole feature – not just this setting – as something to migrate away from before PHP 9.0.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Usage of session.trans_sid_tags INI setting is deprecated

Description

session.trans_sid_tags lists which HTML tag/attribute pairs (e.g. a=href, form=) PHP rewrites to inject the session ID when trans sid (session.use_trans_sid) output rewriting is active. Trans sid – propagating the session ID through the URL and hidden form fields instead of only a cookie – is a legacy mechanism being phased out because it leaks session IDs into logs, the Referer header, and shared/bookmarked links.

As of PHP 8.4, setting session.trans_sid_tags to anything other than its default value (a=href,area=href,frame=src,form=) emits this deprecation notice, as part of a broader deprecation of GET/POST (URL-based) session propagation ahead of its removal in PHP 9.0.

Example

<?php

// Changing it away from its default list of tags triggers the
// deprecation as soon as it's applied.
ini_set('session.trans_sid_tags', 'a=href');

?>

Literal Examples

  • ini_set(): Usage of session.trans_sid_tags INI setting is deprecated

Alternatives

  • Leave session.trans_sid_tags at its default and keep session.use_trans_sid disabled (its own default), relying on cookies only.
  • If trans sid is still required for a specific legacy integration, treat the whole feature – not just this setting – as something to migrate away from before PHP 9.0.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Use of “parent” in callables is deprecated

Description

Since PHP 8.2, it is not possible anymore to use parent as a string, when creating a callable. parent is a keyword with contextual meaning. Then, it has little meaning as a string and leads to confusion.

Example

<?php

class X {
    static function foo() {
        echo __METHOD__;
    }

    static function test() {
        call_user_func(array('parent','foo'));
    }
}

X::test();

?>

Alternatives

  • Use parent::class to make this class name non-ambiguous.
  • Use another way to create a closure for the method, such as parent::foo(...).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See codes/parentInCallable

Use of “self” in callables is deprecated

Description

Since PHP 8.2, it is not possible anymore to use self as a string, when creating a callable. self is a keyword with contextual meaning. Then, it has little meaning as a string and leads to confusion.

Example

<?php

class X {
    static function foo() {
        echo __METHOD__;
    }

    static function test() {
        call_user_func(array('self','foo'));
    }
}

X::test();

?>

Alternatives

  • Use self::class to make this class name non-ambiguous.
  • Use another way to create a closure for the method, such as self::foo(...).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See codes/selfInCallable

Use of “static” in callables is deprecated

Description

Since PHP 8.2, it is not possible anymore to use static as a string, when creating a callable. static is a keyword with contextual meaning. Then, it has little meaning as a string and leads to confusion.

Example

<?php

class X {
    static function foo() {
        echo __METHOD__;
    }

    static function test() {
        call_user_func(array('static','foo'));
    }
}

X::test();

?>

Alternatives

  • Use static::class to make this class name non-ambiguous.
  • Use another way to create a closure for the method, such as static::foo(...).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See codes/staticInCallable

Use of "parent" in callables is deprecated

Description

The relative class names self, parent and static only have a meaning inside a class body, resolved against the scope currently active. Nothing stops a string or array callable from containing parent, e.g. 'parent::method' or ['parent', 'method'], but such a callable has no fixed target: PHP resolves parent against the parent of whatever class scope happens to be active where the callable is finally invoked (through call_user_func(), is_callable(), etc.), which can be a completely different class hierarchy than the one where the string was built.

As of PHP 8.2, resolving a callable that uses parent this way emits Use of "parent" in callables is deprecated. The callable still works for now – and keeps resolving against the invocation-time scope – but this implicit, moving-target behaviour is expected to be removed in a future version.

Example

<?php

class Base {
    public static function bar() {
        return 'Base::bar called';
    }
}

class Foo extends Base {
    public static function make() {
        // The string is built here, inside Foo, but 'parent' is NOT
        // resolved against Foo's parent (Base) -- see where it is
        // actually invoked below.
        return 'parent::bar';
    }
}

class OtherBase {
    public static function bar() {
        return 'OtherBase::bar called';
    }
}

class Other extends OtherBase {
    public function run($callable) {
        // 'parent' resolves against THIS scope's parent (OtherBase),
        // not against Base, which is Foo's parent.
        var_dump(call_user_func($callable));
    }
}

$callable = Foo::make(); // the string 'parent::bar'
(new Other)->run($callable); // prints 'OtherBase::bar called', not 'Base::bar called'

?>

Literal Examples

  • Use of “parent” in callables is deprecated

Alternatives

  • Replace ‘parent::method’ with parent::class . ‘::method’ so the callable is no longer context-dependent.
  • For array callables, use [parent::class, ‘method’] instead of [‘parent’, ‘method’].
  • Use first-class callable syntax (PHP 8.1+), e.g. parent::method(…), when the callable is created and used in the same place.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Use of "self" in callables is deprecated

Description

The relative class names self, parent and static only have a meaning inside a class body, resolved against the scope currently active. Nothing stops a string or array callable from containing one of them, e.g. 'self::method' or ['self', 'method'], but such a callable has no fixed target: PHP resolves self against whatever class scope happens to be active where the callable is finally invoked (through call_user_func(), is_callable(), etc.), which can be a completely different class than the one where the string was built.

As of PHP 8.2, resolving a callable that uses self this way emits Use of "self" in callables is deprecated. The callable still works for now – and keeps resolving against the invocation-time scope – but this implicit, moving-target behaviour is expected to be removed in a future version.

Example

<?php

class Foo {
    public static function bar() {
        return 'Foo::bar called';
    }

    public static function make() {
        // The string is built here, inside Foo, but 'self' is NOT
        // resolved against Foo -- see where it is actually invoked below.
        return 'self::bar';
    }
}

class Other {
    public static function bar() {
        return 'Other::bar called';
    }

    public function run($callable) {
        // 'self' resolves against THIS scope (Other), the one active
        // where the callable is invoked, not where the string was built.
        var_dump(call_user_func($callable));
    }
}

$callable = Foo::make(); // the string 'self::bar'
(new Other)->run($callable); // prints 'Other::bar called', not 'Foo::bar called'

?>

Literal Examples

  • Use of “self” in callables is deprecated

Alternatives

  • Replace ‘self::method’ with self::class . ‘::method’ (or the target class’s own name) so the callable is no longer context-dependent.
  • For array callables, use [self::class, ‘method’] instead of [‘self’, ‘method’].
  • Use first-class callable syntax (PHP 8.1+), e.g. self::method(…), when the callable is created and used in the same place.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Use of "static" in callables is deprecated

Description

The relative class names self, parent and static only have a meaning inside a class body, resolved against the scope currently active. Nothing stops a string or array callable from containing static, e.g. 'static::method' or ['static', 'method'], but such a callable has no fixed target: PHP resolves static using late static binding against whatever called scope happens to be active where the callable is finally invoked (through call_user_func(), is_callable(), etc.), which can be a completely different class than the one where the string was built.

As of PHP 8.2, resolving a callable that uses static this way emits Use of "static" in callables is deprecated. The callable still works for now – and keeps resolving against the invocation-time called scope – but this implicit, moving-target behaviour is expected to be removed in a future version.

Example

<?php

class Foo {
    public static function bar() {
        return 'Foo::bar called';
    }

    public static function make() {
        // The string is built here, inside Foo, but 'static' is NOT
        // resolved against Foo -- see where it is actually invoked below.
        return 'static::bar';
    }
}

class Base {
    public static function bar() {
        return 'Base::bar called';
    }

    public static function run($callable) {
        // 'static' resolves against the called scope active HERE
        // (Sub, since run() was invoked as Sub::run()), not against Foo.
        var_dump(call_user_func($callable));
    }
}

class Sub extends Base {
    public static function bar() {
        return 'Sub::bar called';
    }
}

$callable = Foo::make(); // the string 'static::bar'
Sub::run($callable); // prints 'Sub::bar called', not 'Foo::bar called'

?>

Literal Examples

  • Use of “static” in callables is deprecated

Alternatives

  • Replace ‘static::method’ with static::class . ‘::method’ so the callable is no longer context-dependent.
  • For array callables, use [static::class, ‘method’] instead of [‘static’, ‘method’].
  • Use first-class callable syntax (PHP 8.1+), e.g. static::method(…), when the callable is created and used in the same place.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Use of iconv.input_encoding is deprecated

Description

iconv.input_encoding used to tell PHP which encoding incoming request data ($_GET, $_POST, etc.) was assumed to be in, for the iconv extension’s own encoding-conversion pass over external input. Having several overlapping encoding-related INI settings, each affecting only part of the request, was a frequent source of mismatched-encoding bugs.

As of PHP 5.6, setting iconv.input_encoding (whether in php.ini or via ini_set()/iconv_set_encoding()) emits this deprecation notice; the single, extension-agnostic default_charset setting should be used instead.

Example

<?php

ini_set('iconv.input_encoding', 'UTF-8');

?>

Literal Examples

  • ini_set(): Use of iconv.input_encoding is deprecated
  • iconv_set_encoding(): Use of iconv.input_encoding is deprecated

Alternatives

  • Leave iconv.input_encoding unset and rely on default_charset instead.
  • Convert incoming input explicitly with iconv() where a specific encoding must be assumed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Use of iconv.internal_encoding is deprecated

Description

iconv.internal_encoding used to control the encoding the iconv_*() functions assumed for strings when no encoding was given explicitly, alongside the separate, more general mbstring.internal_encoding/mbstring.language and the character encoding used when generating output. Having several overlapping encoding-related INI settings, each affecting only part of the request, was a frequent source of mismatched-encoding bugs.

As of PHP 5.6, setting iconv.internal_encoding (whether in php.ini or via ini_set()/iconv_set_encoding()) emits this deprecation notice; the single, extension-agnostic default_charset setting should be used instead.

Example

<?php

ini_set('iconv.internal_encoding', 'UTF-8');

?>

Literal Examples

  • ini_set(): Use of iconv.internal_encoding is deprecated
  • iconv_set_encoding(): Use of iconv.internal_encoding is deprecated

Alternatives

  • Leave iconv.internal_encoding unset and rely on default_charset instead.
  • Pass the encoding explicitly to each iconv_*() call rather than relying on any implicit internal encoding.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Use of iconv.output_encoding is deprecated

Description

iconv.output_encoding used to tell PHP which encoding to convert output into, via the iconv extension’s own output handler. Having several overlapping encoding-related INI settings, each affecting only part of the request, was a frequent source of mismatched-encoding bugs.

As of PHP 5.6, setting iconv.output_encoding (whether in php.ini or via ini_set()/iconv_set_encoding()) emits this deprecation notice; the single, extension-agnostic default_charset setting should be used instead.

Example

<?php

ini_set('iconv.output_encoding', 'UTF-8');

?>

Literal Examples

  • ini_set(): Use of iconv.output_encoding is deprecated
  • iconv_set_encoding(): Use of iconv.output_encoding is deprecated

Alternatives

  • Leave iconv.output_encoding unset and rely on default_charset instead.
  • Convert generated output explicitly with iconv() where a specific output encoding must be guaranteed.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Use of mbstring.http_input is deprecated

Description

mbstring.http_input used to tell the mbstring extension which encoding(s) to assume for incoming HTTP request data, so it could transparently convert it (in combination with mbstring.encoding_translation).

This mechanism predates, and overlaps with, the language-level input_encoding directive, and having two separate configuration surfaces for the same concern is a frequent source of confusion. mbstring.http_input has been deprecated since PHP 5.6.0, though the deprecation notice is only emitted when the directive is actually set.

Example

<?php

ini_set('mbstring.http_input', 'UTF-8');

?>

Alternatives

  • Use the input_encoding INI directive instead of mbstring.http_input.

In more recent PHP versions, this error message is now :ref:use-of-mbstring.http_output-is-deprecated.

Use of mbstring.http_output is deprecated

Description

mbstring.http_output used to tell the mbstring extension which encoding to convert outgoing HTTP response data to, so it could transparently re-encode output (in combination with mbstring.encoding_translation and the mb_output_handler output buffer handler).

This mechanism predates, and overlaps with, the language-level output_encoding directive, and having two separate configuration surfaces for the same concern is a frequent source of confusion. mbstring.http_output has been deprecated since PHP 5.6.0, though the deprecation notice is only emitted when the directive is actually set.

Example

<?php

ini_set('mbstring.http_output', 'UTF-8');

?>

Alternatives

  • Use the output_encoding INI directive instead of mbstring.http_output.

In previous PHP versions, this error message used to be :ref:use-of-mbstring.http_input-is-deprecated. In more recent PHP versions, this error message is now :ref:use-of-mbstring.internal_encoding-is-deprecated.

Use of mbstring.internal_encoding is deprecated

Description

mbstring.internal_encoding used to set the default encoding assumed by mbstring functions when no explicit encoding argument is given (e.g. mb_strlen($str)).

This mechanism predates, and overlaps with, the language-level default_charset directive, which mbstring functions now fall back to when their own internal encoding has not been set explicitly at runtime via mb_internal_encoding(). Having two separate configuration surfaces for the same concern is a frequent source of confusion. mbstring.internal_encoding has been deprecated since PHP 5.6.0, though the deprecation notice is only emitted when the directive is actually set.

Example

<?php

ini_set('mbstring.internal_encoding', 'UTF-8');

?>

Alternatives

  • Use the default_charset INI directive instead of mbstring.internal_encoding.
  • Call mb_internal_encoding() at runtime if a specific encoding must be set programmatically.

In previous PHP versions, this error message used to be :ref:use-of-mbstring.http_output-is-deprecated.

Use of warnings for SQLite3 is deprecated

Description

The SQLite3 extension historically reported errors (such as a failed query) by emitting an E_WARNING and returning false, which is inconsistent with the exception-based error handling used elsewhere in PHP, and requires manual checking of every return value. SQLite3::enableExceptions(true) switches to throwing SQLite3Exception instead, and has been available for a long time as an opt-in.

As of PHP 8.3.0, the legacy warning-based mode is deprecated: calling SQLite3::enableExceptions() with false (or not calling it at all, since false is the default) raises a deprecation notice.

Example

<?php

$db = new SQLite3(':memory:');

// Explicitly keeps the legacy, warning-based error mode.
$db->enableExceptions(false);

?>

Alternatives

  • Call $db->enableExceptions(true) right after opening the connection, and handle SQLite3Exception instead of checking return values for false.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See SQLite3::enableExceptions

Using “_” as %s is deprecated since 8.4

Description

_ (underscore) is a valid class name, although it has become a reserved PHP word in PHP 8.4. In the future, it may be used for pattern matching, and by anticipation, it is not allowed for other usage that may ultimately conflict with it.

This applies to classes, traits, interfaces and enumerations. There is already an extension function called _, which is an alias of gettext, from the eponymous extension.

This applies in every name spaces.

Example

<?php

class _ {}

?>

Alternatives

  • Use another name.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ClassUnderscore

Using $this when not in object context

Description

A static method is also called a class method: it may be executed without a dedicated object. That object is usually made available in the method, via the pseudo variable $this.

Hence, when a method is marked as static, the variable $this is not made available, and cannot be used.

In the error message, the ‘object context’ refers to a class, enum or trait. $this must be localised inside such structures; even more, it is only used in the body of a method of such structure.

Inside a class, trait or enum, static methods, static closures and static arrow functions shall not use $this. The two last ones are marked also with the static keyword.

Example

<?php

class X {
    static function foo() { print $this; }
}

var_dump(x::foo());

?>

Alternatives

  • Make the method non-static, and use $this.
  • Keep the method static, and remove calls to $this.
  • Make the closure non-static.
  • Make the arrow function non-static.

Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead

Description

The interpolation syntax ${expression} is deprecated. It takes an expression (here, a concatenation) to build the name of the variable that is used in the end. It is recommended to update the syntax with a compatible one or use concatenation, before the syntax is removed.

Example

<?php

$foo = 'bar';
$bar = 'xyz';
var_dump("foo is $\{$foo}");

?>

Alternatives

  • Use {} instead.
  • Use concatenation instead.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See dollar_curly_expression

Using in strings is deprecated, use {$var} instead

Description

For variable interpolation, the double quote strings used two variants: ${var} ($ is outside the brackets), and {$var} ($ is inside the brackets).

The first one has been deprecated, and it should be removed in PHP 9.0.

Example

<?php

$var = 'abc';

echo ;

?>

Alternatives

  • Replace ${var} with $var inside the string. It should work most of the time.
  • Replace ${var} with {$var} inside the string. It works every time.

Using an object as a backing array for %s is deprecated, as it allows violating class constraints and invariants

Description

It is not allowed anymore to create an ArrayObject based on an object. This leads to many unexpected behaviors, that are not supported anymore by PHP.

Example

<?php

$object = new stdClass;
$object->a = 1;

new ArrayObject($object);

?>

Literal Examples

  • Using an object as a backing array for ArrayObject is deprecated, as it allows violating class constraints and invariants

Alternatives

  • Cast the object to array before using it with ArrayObject.
  • Do not use ArrayObject.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Using array_key_exists() on objects is deprecated.

Description

array_key_exists() used to accept both arrays and objects. In array cases, it looks for an index in the array keys, and in the object case, it looks for a property in the public properties.

array_key_exists() only works with array: it doesn’t work with ArrayAccess object, and yields the same error.

In PHP 7.4, this feature was deprecated, with the eponymous message. In PHP 8.0, it is now turned into a type error: the second argument must be an array.

Example

<?php

class X {
    public string $property = '';
}

$object = new X();

array_key_exists($object, 'index');

?>

Alternatives

  • Check if the variable is actually an object before using it with array_key_exists().
  • Check if the variable is actually an object before using it with array_key_exists().

In more recent PHP versions, this error message is now :ref:argument-#%d-($%s)-must-be-of-type-%s,-%s-given.

Using empty file as ZipArchive is deprecated

Description

ZipArchive::open() accepts an existing, empty (0-byte) file together with the ZipArchive::CREATE flag, in order to turn it into a fresh archive. This relied on treating a 0-byte file as an implicit, valid, empty archive.

Since libzip 1.6.0, the library underlying the zip extension no longer considers an empty file a valid archive on its own, and PHP has to work around that internally. As of PHP 8.0.0, doing so is deprecated. This is commonly triggered by patterns using tempnam() (which creates an empty placeholder file) before opening it as an archive.

Example

<?php

$path = tempnam(sys_get_temp_dir(), 'zip');
// tempnam() leaves an empty (0-byte) file behind.

$zip = new ZipArchive();
$zip->open($path, ZipArchive::CREATE);

?>

Alternatives

  • Delete the empty file before calling $zip->open($path, ZipArchive::CREATE), so it does not exist yet.
  • Use the ZipArchive::OVERWRITE flag (optionally combined with ZipArchive::CREATE) instead of relying on an existing empty file.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See ZipArchive::open

Using more than “ ZEND_LONG_FMT “ filters in a php://filter URL is deprecated

Description

A php://filter/... URL can chain any number of stream filters with |. To bound the cost of building very long chains, PHP now caps the number of filters read from a single URL at 16 (ZEND_LONG_FMT is a printf-style placeholder for a platform-independent long integer, substituted with 16 in the actual message) unless a higher limit is configured explicitly. Exceeding that default without configuring it emits this deprecation; a future version will make the limit a hard error instead.

Example

<?php

$filters = str_repeat('string.toupper|', 17) . 'string.toupper';

echo file_get_contents("php://filter/$filters/resource=data:text/plain,hello");

?>

Literal Examples

  • Using more than 16 filters in a php://filter URL is deprecated, set this limit using the stream context option max_filter_count, or use stream_filter_append

Alternatives

  • Set the stream context option filter => max_filter_count to the number of filters you actually need, e.g. via stream_context_create(['filter' => ['max_filter_count' => 32]]).
  • Build the chain with repeated stream_filter_append() calls instead of a long php://filter URL; it is not subject to this limit.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Using more than %d filters in a php://filter URL is deprecated

Description

The php://filter stream wrapper lets several conversion filters be chained in a single URL, separated by |. By default, PHP now limits the number of filters that can be chained this way to 16; exceeding that limit triggers this deprecation, and a future version is expected to turn it into a hard failure.

The limit only applies to filters listed directly in a php://filter URL. It does not affect filters added programmatically with stream_filter_append(), nor is it lowered unless a smaller max_filter_count is explicitly configured on the stream context (in which case exceeding it already fails immediately, without this deprecation).

Restricting the default chain length also mitigates a known exploitation technique (“PHP filter chains”) that abuses very long filter chains to convert an arbitrary-read vulnerability into code execution by repeatedly transcoding a string in memory.

Example

<?php

$filters = implode('|', array_fill(0, 17, 'string.toupper'));

// deprecated: more than 16 filters chained directly in the URL
$data = file_get_contents("php://filter/read=$filters/resource=php://memory");

?>

Literal Examples

  • Using more than 16 filters in a php://filter URL is deprecated

Alternatives

  • Raise or override the default limit by setting the filter.max_filter_count stream context option, e.g. stream_context_create(['filter' => ['max_filter_count' => 100]]).
  • Use stream_filter_append() to add filters programmatically instead of chaining a long list of them in the URL.
  • Reduce the number of chained filters if the default of 16 is sufficient.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Using null as an array offset is deprecated, use an empty string instead

Description

Avoid using null as an array index. PHP converts it silently to an empty string anyway.

Example

<?php

$array = ['a' => 2];
$array[null] = 3;

?>

Alternatives

  • Replace the null with an empty string.
  • Check the value before using it as an array index.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See NullAsArrayOffset

Using null as the key parameter for array_key_exists() is deprecated, use an empty string instead

Description

null cannot be used as an array index anymore, since PHP 8.5. It is deprecated. As such, there is no point anymore to in passing such values to the first argument of array_key_exists(), and this is also deprecated.

Example

<?php

$array = [null => 1];
var_dump(array_key_exists(null, $array));

?>

Alternatives

  • Use the coalesce operator ?? to turn the null into another value, such as empty string.
  • Replace the null value by the empty string.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See NullAsArrayOffset, NullWithArrayKeyExists

Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated,

Description

spl_autoload_unregister() normally removes one specific autoload function that was previously registered with spl_autoload_register(). As an undocumented side effect, passing the engine’s own spl_autoload_call() function as the callback acted as a magic value that unregistered all autoloaders at once, regardless of how many were registered or by which part of the code.

This implicit, all-or-nothing shortcut is deprecated as of PHP 8.5 because it is easy to trigger by accident (any code that unregisters its own autoloader using the wrong callable name) and because it silently affects autoloaders registered by unrelated libraries. Use spl_autoload_functions() to list every registered autoloader and unregister them individually instead.

Example

<?php

spl_autoload_register(function ($class) {
    // custom autoloading logic
});

// Passing the internal spl_autoload_call() as a callback is a
// magic value that unregisters every registered autoloader at once.
spl_autoload_unregister('spl_autoload_call');

?>

Literal Examples

  • Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated, use spl_autoload_functions() and spl_autoload_unregister() on each entry instead

Alternatives

  • Iterate over spl_autoload_functions() and call spl_autoload_unregister() on each entry to unregister every autoloader explicitly.
  • Keep a reference to the specific autoloader callable your own code registered, and unregister only that one instead of relying on the magic shortcut.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Using the $num_points parameter is deprecated

Description

imagepolygon() and imagefilledpolygon() take an array of point coordinates and a $num_points argument stating how many vertices that array describes. In practice, $num_points is almost always equal to count($points) / 2, since the array must contain the x/y pairs for exactly that many points.

Because the value is redundant with the actual size of $points, and mismatches between the two used to be a common source of bugs (or of manual, brittle count() / 2 computations at every call site), the $num_points argument is deprecated as of PHP 8.1.0 in favor of omitting it and letting PHP derive the point count from the array itself.

Example

<?php

$im = imagecreatetruecolor(100, 100);
$color = imagecolorallocate($im, 255, 0, 0);
$points = [10, 10, 50, 90, 90, 10];

imagepolygon($im, $points, 3, $color);

?>

Alternatives

  • Omit $num_points entirely, e.g. imagepolygon($im, $points, $color); $points must then contain an even number of elements.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See imagepolygon, imagefilledpolygon

Value for class is not a string

Description

Exception::getTraceAsString() (and the trace formatting used when an uncaught exception is printed) rebuilds a readable string from the exception’s internal trace array, one frame at a time. Each frame is expected to store its class entry, when present, as a string.

The trace array is normally built by the engine and always well-formed, but it can be replaced or altered by user code, typically through ReflectionProperty::setValue() on the trace property. If a frame’s class entry is present but is not a string, this warning is raised while the frame is rendered as [unknown] instead of the real class name.

Example

<?php

$e = new Exception();

$ref = new ReflectionProperty($e, 'trace');
$ref->setValue($e, [
    ['class' => null, 'type' => '::', 'function' => 'foo'],
]);

echo $e->getTraceAsString();

?>

Literal Examples

  • Value for class is not a string

Alternatives

  • Do not overwrite the trace property of an exception with malformed frame data; if you need custom trace-like data, use a separate property.
  • When constructing trace frames manually, make sure class, function and type are always strings.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

value must be between 0 and %d

Description

imagefilter() with IMG_FILTER_SCATTER accepts an optional 5th argument: an array of color indexes to scatter, each of which is converted to a C int and must be a non-negative color index.

Starting in PHP 8.5, GD validates every element of that array and rejects negative or out-of-range values with a ValueError naming the offending argument, instead of passing a meaningless value through to the underlying library.

Example

<?php

$im = imagecreatetruecolor(100, 100);

imagefilter($im, IMG_FILTER_SCATTER, 4, 4, [-1]);

?>

Literal Examples

  • imagefilter(): Argument #5 value must be between 0 and 2147483647

Alternatives

  • Only pass non-negative color indexes, between 0 and 2147483647, in the color array given to imagefilter(IMG_FILTER_SCATTER).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Value of type %s is not callable

Description

There was an attempt to call a function whose name was provided in a variable, but that value could not be related to a callable code.

  • null : not a callable
  • true, false : booleans are not callable
  • int : integers are not callable
  • float : float are not callable
  • array : arrays are callable when they have two elements, with keys 0 and 1. First one is a class or an object of that class, the second is a string with a visible method name on that class. Otherwise, they are not valid callables.
  • string : strings are callable when they represent a function, with the leading backslash, \strlen, or a method, with a class name, a double colon ::, and a visible method name. Otherwise, they are not valid callables.
  • object : object are callable when their class has a __invoke method. This might be through a parent, like Closure. Otherwise, objects are not callable, although their method are.

All of these may be checked with a call to is_callable() on the variable, before using it.

Example

<?php

$method = null;
$method();

?>

Literal Examples

  • Value of type int is not callable
  • Value of type bool is not callable
  • Value of type string is not callable
  • Value of type float is not callable

Alternatives

  • Check the variable with is_callable(), before using it with the call syntax.
  • Use one of the available format.

Variadic parameter cannot have a default value

Description

A variadic parameter, marked with ..., already collects zero or more arguments into an array: when no argument is passed for it, it is simply an empty array. There is no meaning in giving it a default value, since the parameter itself can never be missing from the call, only empty.

This is a compile time check.

Example

<?php

function foo(...$a = []) {}

?>

Alternatives

  • Remove the default value from the variadic parameter.
  • Check inside the function body whether the collected array is empty, instead of relying on a default value.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Variadic placeholder may only appear once

Description

The … placeholder used for partial function application (PHP 8.5) stands for all of the function’s remaining, not-yet-supplied parameters, which become the parameters of the resulting Closure. Using it more than once in the same call is ambiguous, since there is only one set of “remaining parameters” to represent, so PHP allows at most one placeholder per call.

Example

<?php

function add($a, $b, $c) {
	return $a + $b + $c;
}

$curried = add(..., ...);

?>

Alternatives

  • Use a single … placeholder per call; wrap the result in an extra closure for any additional free parameters.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Variadic placeholder must be last

Description

The … placeholder used for partial function application (PHP 8.5) introduces the parameters of the resulting Closure, made of every parameter of the original function that was not already given a fixed value. Because everything before it is treated as a fixed, bound argument, the placeholder itself must come last in the call; PHP has no way to bind arguments positioned after it.

Example

<?php

function add($a, $b, $c) {
	return $a + $b + $c;
}

$curried = add(..., 2, 3);

?>

Alternatives

  • Put every fixed argument before …, and keep … as the final argument: add(1, 2, …).

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Visibility of property %s::$%s must not be weaker than set visibility

Description

When using asymmetric visibility, it is not allowed to have a weaker public visibility for writing than for reading (private). This would be akin to a variable which can be written from the public scope, which is accessible to the class, but not read from that scope. As such, the set visibility must be at most the same than the get one.

Using the same level of visibility with both options is possible, although useless.

Example

<?php

class X {
   private public(set) string $p;

	// valid but useless
   //protected protected(set) string $p;

	// valid
   public public(set) string $p;
}

?>

Literal Examples

  • Visibility of property x::$p must not be weaker than set visibility

Alternatives

  • Make the property private, and set up an accessor method.
  • Use the magic methods __get() and __set() to set up that kind of feature.

Void can only be used as a standalone type

Description

void is a special return type, indicating that a function or method returns no useful value. Since it represents the absence of a value, it cannot be combined with other types in a union, nor made nullable: it can only be used on its own, as the sole return type of a function or method.

Example

<?php

function foo(): int|void {}

?>

Alternatives

  • Remove the other types, and use void alone.
  • Remove void, and keep the other type(s) alone.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

void cannot be used as a parameter type

Description

Void is a type, that can only be used with return type, on methods or functions. Here, void represents the absence of value: this is not possible for a property or an argument. The null value is then the closest possible type that can be assigned to a property, yet representing no value.

Example

<?php

  function foo(void $p) { }

?>

Alternatives

  • Use another type for the argument.
  • Remove the argument.
  • Use the null type.

WeakMap key must be an object

Description

WeakMap associates data with objects, and it holds its keys weakly: when a key object is destroyed, its entry is removed automatically. Because of this, only objects can be used as keys. Any other value, such as a string, an integer, an array or null, triggers a TypeError.

The check applies to every access to a WeakMap through array syntax: assignment, reading, isset(), empty() and unset().

If you need to index data by a scalar value, use a regular array instead.

Example

<?php

$map = new WeakMap();

// WeakMap keys are held weakly, so they must be objects
$map['name'] = 'Damien';

?>

Literal Examples

  • WeakMap key must be an object

Alternatives

  • Use an object as the key, such as the instance the data relates to.
  • Use a regular array when the keys are strings or integers, as arrays do not need weak references.
  • Check the key with is_object() before accessing the WeakMap.

Changed Behavior

This error may appear following an evolution in behavior, in previous versions. See

Write of %zu bytes failed with errno=%d %s

Description

The errno=22 happens when the path is an invalid path. It may hold forbidden characters, such as colon : or space ' '.

Example

<?php

file_put_contents($path, $content);

?>

Literal Examples

  • Write of 200 bytes failed with errno=22

Alternatives

  • Check the path of the file.

Wrong encoding, conversion from “%s” to “%s” is not allowed

Description

This message reports that the origin or the destination encoding when calling iconv() is not supported on this server. It might be a typo in the encoding name, or an uninstalled encoding on the system. Note that lower case and uppercase do not matter.

Example

<?php

$string = iconv('utf-8', 'not-an-encoding', $source);

?>

Literal Examples

  • Wrong encoding, conversion from “utf-8” to “utf-9” is not allowed
  • Wrong encoding, conversion from “bag5” to “utf-8” is not allowed

Alternatives

  • Check the names of the encodings for typos.
  • Check the installed encodings on the system.
  • Check the encodings actually exist.