Skip to content

Latest commit

 

History

History
2569 lines (1848 loc) · 42.8 KB

issues.md

File metadata and controls

2569 lines (1848 loc) · 42.8 KB

Issue types

AbstractInstantiation

Emitted when an attempt is made to instantiate an abstract class:

abstract class A {}
new A();

ArgumentTypeCoercion

Emitted when calling a function with an argument which has a less specific type than the function expects

class A {}
class B extends A {}

function takesA(A $a) : void {
    takesB($a);
}
function takesB(B $b) : void {}

AssignmentToVoid

Emitted when assigning from a function that returns void:

function foo() : void {}
$a = foo();

CircularReference

Emitted when a class references itself as one of its parents

class A extends B {}
class B extends A {}

ConflictingReferenceConstraint

Emitted when a by-ref variable is set in two different branches of an if to different types.

 class A {
    /** @var int */
    private $foo;

    public function __construct(int &$foo) {
        $this->foo = &$foo;
    }
}

class B {
    /** @var string */
    private $bar;

    public function __construct(string &$bar) {
        $this->bar = &$bar;
    }
}

if (rand(0, 1)) {
    $v = 5;
    $c = (new A($v)); // $v is constrained to an int
} else {
    $v = "hello";
    $c = (new B($v)); // $v is constrained to a string
}

$v = 8;

ContinueOutsideLoop

Emitted when encountering a continue statement outside a loop context.

$a = 5;
continue;

DeprecatedClass

Emitted when referring to a deprecated class:

/** @deprecated */
class A {}
new A();

DeprecatedConstant

Emitted when referring to a deprecated constant:

class A {
    /** @deprecated */
    const FOO = 'foo';
}

echo A::FOO;

DeprecatedFunction

Emitted when calling a deprecated function:

/** @deprecated */
function foo() : void {}
foo();

DeprecatedInterface

Emitted when referring to a deprecated interface

/** @deprecated */
interface I {}

class A implements I {}

DeprecatedMethod

Emitted when calling a deprecated method on a given class:

class A {
    /** @deprecated */
    public function foo() : void {}
}
(new A())->foo();

DeprecatedProperty

Emitted when getting/setting a deprecated property of a given class

class A {
    /**
     * @deprecated
     * @var ?string
     */
    public $foo;
}
(new A())->foo = 5;

DeprecatedTrait

Emitted when referring to a deprecated trait:

/** @deprecated */
trait T {}
class A {
    use T;
}

DocblockTypeContradiction

Emitted when conditional doesn't make sense given the docblock types supplied.

/**
 * @param string $s
 *
 * @return void
 */
function foo($s) {
    if ($s === 5) { }
}

DuplicateArrayKey

Emitted when an array has a key more than once

$arr = [
    'a' => 1,
    'b' => 2,
    'c' => 3,
    'c' => 4,
];

DuplicateClass

Emitted when a class is defined twice

class A {}
class A {}

DuplicateFunction

Emitted when a function is defined twice

function foo() : void {}
function bar() : void {}
function foo() : void {}

DuplicateMethod

Emitted when a method is defined twice

class A {
    public function foo() {}
    public function foo() {}
}

DuplicateParam

Emitted when a function has a param defined twice

function foo(int $b, string $b) {}

EmptyArrayAccess

Emitted when attempting to access a value on an empty array

$a = [];
$b = $a[0];

FalsableReturnStatement

Emitted if a return statement contains a false value, but the function return type does not allow false

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return false; // emitted here
}

FalseOperand

Emitted when using false as part of an operation (e.g. +, ., ^ etc.)

echo false . 'hello';

ForbiddenCode

Emitted when Psalm encounters a var_dump, exec or similar expression that may make your code more vulnerable

var_dump("bah");

ForbiddenEcho

Emitted when Psalm encounters an echo statement and the forbidEcho flag in your config is set to true

echo("bah");

ImplementedParamTypeMismatch

Emitted when a class that inherits another, or implements an interface, has docblock param type that's entirely different to the parent. Subclasses of the parent return type are permitted, in docblocks.

class D {
    /** @param string $a */
    public function foo($a): void {}
}

class E extends D {
    /** @param int $a */
    public function foo($a): void {}
}

ImplementedReturnTypeMismatch

Emitted when a class that inherits another, or implements an interface, has docblock return type that's entirely different to the parent. Subclasses of the parent return type are permitted, in docblocks.

class A {
    /** @return bool */
    public function foo() {
        return true;
    }
}
class B extends A {
    /** @return string */
    public function foo()  {
        return "hello";
    }
}

ImplicitToStringCast

Emitted when implicitly converting an object with a __toString method to a string

class A {
    public function __toString() {
        return "foo";
    }
}

function takesString(string $s) : void {}

takesString(new A);

ImpureFunctionCall

Emitted when calling an impure function from a function or method marked as pure.

function impure(array $a) : array {
    /** @var int */
    static $i = 0;

    ++$i;

    $a[$i] = 1;

    return $a;
}

/** @psalm-pure */
function filterOdd(array $a) : void {
    impure($a);
}

ImpureMethodCall

Emitted when calling an impure method from a function or method marked as pure.

class A {
    public int $a = 5;

    public function foo() : void {
        $this->a++;
    }
}

/** @psalm-pure */
function filterOdd(int $i, A $a) : ?int {
    $a->foo();

    if ($i % 2 === 0 || $a->a === 2) {
        return $i;
    }

    return null;
}

ImpurePropertyAssignment

Emitted when updating a property value from a function or method marked as pure.

class A {
    public int $a = 5;
}

/** @psalm-pure */
function filterOdd(int $i, A $a) : ?int {
    $a->a++;

    if ($i % 2 === 0 || $a->a === 2) {
        return $i;
    }

    return null;
}

ImpureStaticVariable

Emitted when attempting to use a static variable from a function or method marked as pure

/** @psalm-pure */
function addCumulative(int $left) : int {
    /** @var int */
    static $i = 0;
    $i += $left;
    return $left;
}

InaccessibleClassConstant

Emitted when a public/private class constant is not accessible from the calling context

class A {
    protected const FOO = 'FOO';
}
echo A::FOO;

InaccessibleMethod

Emitted when attempting to access a protected/private method from outside its available scope

class A {
    protected function foo() : void {}
}
echo (new A)->foo();

InterfaceInstantiation

Emitted when an attempt is made to instantiate an interface:

interface I {}
new I();

InaccessibleProperty

Emitted when attempting to access a protected/private property from outside its available scope

class A {
    /** @return string */
    protected $foo;
}
echo (new A)->foo;

InternalClass

Emitted when attempting to access a class marked as internal an unrelated namespace or class, or attempting to access a class marked as psalm-internal to a different namespace.

namespace A {
    /**
     * @internal
     */
    class Foo { }
}

namespace B {
    class Bat {
        public function batBat() {
            $a = new \A\Foo();
        }
    }
}

InternalMethod

Emitted when attempting to access a method marked as internal an unrelated namespace or class, or attempting to access a method marked as psalm-internal to a different namespace.

namespace A {
    class Foo {
        /**
         * @internal
         */
        public static function barBar(): void {
        }
    }
}
namespace B {
    class Bat {
        public function batBat() {
            \A\Foo::barBar();
        }
    }
}

InternalProperty

Emitted when attempting to access a property marked as internal from an unrelated namespace or class, or attempting to access a property marked as psalm-internal to a different namespace.

namespace A {
    class Foo {
        /**
         * @internal
         * @var ?int
         */
        public $foo;
    }
}

namespace B {
    class Bat {
        public function batBat() : void {
            echo (new \A\Foo)->foo;
        }
    }
}

InvalidArgument

Emitted when a supplied function/method argument is incompatible with the method signature or docblock one.

class A {}
function foo(A $a) : void {}
foo("hello");

InvalidArrayAccess

Emitted when attempting to access an array offset on a value that does not permit it

$arr = 5;
echo $arr[0];

InvalidArrayAssignment

Emitted when attempting to assign a value on a non-array

$arr = 5;
$arr[0] = 3;

InvalidArrayOffset

Emitted when attempting to access an array using a value that's not a valid offset for that array

$a = [5, 20, 18];
echo $a["hello"];

InvalidCast

Emitted when attempting to cast a value that's not castable

class A {}
$a = new A();
$b = (string)$a;

InvalidCatch

Emitted when trying to catch a class/interface that doesn't extend Exception or implement Throwable

class A {}
try {
    $worked = true;
}
catch (A $e) {}

InvalidClass

Emitted when referencing a class with the wrong casing

class Foo {}
(new foo());

InvalidStringClass

Emitted when you have allowStringToStandInForClass="false" in your config and you’re passing a string instead of calling a class directly

class Foo {}
$a = "Foo";
new $a();

InvalidClone

Emitted when trying to clone a value that's not cloneable

$a = "hello";
$b = clone $a;

InvalidDocblock

Emitted when there's an error in a docblock type

/** @var array() */
$a = [];

InvalidDocblockParamName

Emitted when a docblock param name doesn’t match up with a named param in the function, if the param doesn’t have a type or its type is array.

/**
 * @param string[] $bar
 */
function foo(array $barb): void {
    //
}

InvalidFalsableReturnType

Emitted when a function can return a nullable value, but its given return type says otherwise

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return false;
}

InvalidFunctionCall

Emitted when calling a function on a non-callable variable

$a = 5;
$b = $a();

InvalidGlobal

Emitted when there's a reference to the global keyword where it's not expected

global $e;

InvalidIterator

Emitted when trying to iterate over a value that's not iterable

$a = 5;
foreach ($a as $b) {}

InvalidMethodCall

Emitted when attempting to call a method on a non-object

$a = 5;
$a->foo();

InvalidNullableReturnType

Emitted when a function can return a nullable value, but its given return type says otherwise

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return null;
}

InvalidOperand

Emitted when using something as an operand that is unexpected

class A {}
echo (new A) . ' ';

InvalidParamDefault

Emitted when a function parameter default clashes with the type Psalm expects the param to be

function foo(int $i = false) : void {}

InvalidParent

Emitted when a function return type is parent, but there's no parent class

class Foo {
    public function f(): parent {}
}

InvalidPassByReference

Emitted when passing a non-variable to a function that expects a by-ref variable

function foo(array &$arr) : void {}
foo([0, 1, 2]);

InvalidPropertyAssignment

Emitted when attempting to assign a property to a non-object

$a = "foo";
$a->bar = "bar";

InvalidPropertyAssignmentValue

Emitted when attempting to assign a value to a property that cannot contain that type.

class A {
    /** @var string|null */
    public $foo;
}
$a = new A();
$a->foo = new stdClass();

InvalidPropertyFetch

Emitted when attempting to get a property from a non-object

$a = "foo";
echo $a->bar;

InvalidReturnStatement

Emitted when a function return statement is incorrect

function foo() : string {
    return 5; // emitted here
}

InvalidReturnType

Emitted when a function’s signature return type is incorrect (often emitted with `InvalidReturnStatement`)
function foo() : int {
    if (rand(0, 1)) {
        return "hello";
    }

    return 5;
}

InvalidScalarArgument

Emitted when a scalar value is passed to a method that expected another scalar type

function foo(int $i) : void {}
function bar(string $s) : void {
    if (is_numeric($s)) {
        foo($s);
    }
}

InvalidScope

Emitted when referring to $this outside a class

echo $this;

InvalidStaticInvocation

Emitted when trying to call an instance function statically

class A {
    /** @var ?string */
    public $foo;

    public function bar() : void {
        echo $this->foo;
    }
}

A::bar();

InvalidTemplateParam

Emitted when using the @extends/@implements annotation to extend a class that has a template type constraint, where that extended value does not satisfy the parent class/interface's constraints.

/**
 * @template T as object
 */
class Base {}

/** @template-extends Base<int> */
class SpecializedByInheritance extends Base {}

InvalidThrow

Emitted when trying to throw a class that doesn't extend Exception or implement Throwable

class A {}
throw new A();

InvalidToString

Emitted when a __toString method does not always return a string

class A {
    public function __toString() {
        return true;
    }
}

LessSpecificImplementedReturnType

Emitted when a class implements an interface method but its return type is less specific than the interface method return type

class A {}
class B extends A {}
interface I {
    /** @return B[] */
    public function foo();
}
class D implements I {
    /** @return A[] */
    public function foo() {
        return [new A, new A];
    }
}

LessSpecificReturnStatement

Emitted when a return statement is more general than the return type given for the function

class A {}
class B extends A {}

function foo() : B {
    return new A(); // emitted here
}

LessSpecificReturnType

Emitted when a return type covers more possibilities than the function itself

function foo() : ?int {
    return 5;
}

LoopInvalidation

Emitted when logic inside a loop invalidates one of the conditionals of the loop

for ($i = 0; $i < 10; $i++) {
    $i = 5;
}

MethodSignatureMismatch

Emitted when a method parameter differs from a parent method parameter, or if there are fewer parameters than the parent method

class A {
    public function foo(int $i) : void {}
}
class B extends A {
    public function foo(string $s) : void {}
}

MethodSignatureMustOmitReturnType

Emitted when a __clone, __construct, or __destruct method is defined with a return type.

class A {
    public function __clone() : void {}
}

MismatchingDocblockParamType

Emitted when an @param entry in a function’s docblock doesn’t match the param typehint,

class A {}
class B {}
/**
 * @param B $b // emitted here
 */
function foo(A $b) : void {}

This, however, is fine:

class A {}
class B extends A {}
/**
 * @param B
 */
function foo(A $b) : void {}

MismatchingDocblockReturnType

Emitted when an @return entry in a function’s docblock doesn’t match the function return typehint

class A {}
class B {}
/**
 * @return B // emitted here
 */
function foo() : A {
    return new A();
}

This, however, is fine:

class A {}
class B extends A {}
/**
 * @return B // emitted here
 */
function foo() : A {
    return new B();
}

MismatchingDocblockParamType

Emitted when an @param entry in a function’s docblock doesn’t match the param typehint

/**
 * @param int $b
 */
function foo(string $b) : void {}

MissingClosureParamType

Emitted when a closure parameter has no type information associated with it

$a = function($a): string {
    return "foo";
};

MissingClosureReturnType

Emitted when a closure lacks a return type

$a = function() {
    return "foo";
};

MissingConstructor

Emitted when non-null properties without default values are defined in a class without a __construct method

class A {
    /** @var string */
    public $foo;
}

MissingDependency

Emitted when referencing a class that doesn’t exist

/**
 * @psalm-suppress UndefinedClass
 */
class A extends B {}

$a = new A();

MissingDocblockType

Emitted when a docblock is present, but the type is missing or badly formatted

/** @var $a */
$a = [];

MissingFile

Emitted when using include or require on a file that does not exist

require("nonexistent.php");

MissingImmutableAnnotation

Emitted when a class inheriting from an immutable interface or class does not also have a @psalm-immutable declaration

/** @psalm-immutable */
interface SomethingImmutable {
    public function someInteger() : int;
}

class MutableImplementation implements SomethingImmutable {
    private int $counter = 0;
    public function someInteger() : int {
        return ++$this->counter;
    }
}

MissingParamType

Emitted when a function parameter has no type information associated with it

function foo($a) : void {}

MissingPropertyType

Emitted when a property is defined on a class without a type

class A {
    public $foo = 5;
}

MissingReturnType

Emitted when a function doesn't have a return type defined

function foo() {
    return "foo";
}

MissingTemplateParam

Emitted when using the @extends/@implements annotation to extend a class without extending all its template params.

/**
 * @template-implements ArrayAccess<int>
 */
class SomeIterator implements ArrayAccess
{
    public function offsetSet($offset, $value) {
    }

    public function offsetExists($offset) {
        return false;
    }

    public function offsetUnset($offset) {
    }

    public function offsetGet($offset) {
        return null;
    }
}

MissingThrowsDocblock

Emitted when a function doesn't have a return type defined

function foo(int $x, int $y) : int {
    if ($y === 0) {
        throw new \InvalidArgumentException('Cannot divide by zero');
    }

    return intdiv($x, $y);
}

MixedArgument

Emitted when Psalm cannot determine the type of an argument

function takesInt(int $i) : void {}
takesInt($_GET['foo']);

MixedArgumentTypeCoercion

Emitted when Psalm cannot be sure that part of an array/iterabble argument's type constraints can be fulfilled

function foo(array $a) : void {
    takesStringArray($a);
}

/** @param string[] $a */
function takesStringArray(array $a) : void {}

MixedArrayAccess

Emitted when trying to access an array offset on a value whose type Psalm cannot determine

echo $_GET['foo'][0];

MixedArrayAssignment

Emitted when trying to assign a value to an array offset on a value whose type Psalm cannot determine

$_GET['foo'][0] = "5";

MixedArrayOffset

Emitted when attempting to access an array offset where Psalm cannot determine the offset type

echo [1, 2, 3][$_GET['foo']];

MixedArrayTypeCoercion

Emitted when trying to access an array with a less specific offset than is expected

/**
 * @param array<array-key, int> $a
 * @param array<int, string> $b
 */
function foo(array $a, array $b) : void {
    foreach ($a as $j => $k) {
        echo $b[$j];
    }
}

MixedAssignment

Emitted when assigning an unannotated variable to a value for which Psalm cannot infer a type more specific than mixed.

$a = $_GET['foo'];

MixedFunctionCall

Emitted when calling a function on a value whose type Psalm cannot infer.

/** @var mixed */
$a = $_GET['foo'];
$a();

MixedInferredReturnType

Emitted when Psalm cannot determine a function's return type

function foo() : int {
    return $_GET['foo'];
}

MixedMethodCall

Emitted when calling a method on a value that Psalm cannot infer a type for

/** @param mixed $a */
function foo($a) : void {
    $a->foo();
}

MixedOperand

Emitted when Psalm cannot infer a type for an operand in any calculated expression

echo $_GET['foo'] + "hello";

MixedPropertyAssignment

Emitted when assigning a property to a value for which Psalm cannot infer a type

/** @param mixed $a */
function foo($a) : void {
    $a->foo = "bar";
}

MixedPropertyFetch

Emitted when retrieving a property on a value for which Psalm cannot infer a type

/** @param mixed $a */
function foo($a) : void {
    echo $a->foo;
}

MixedPropertyTypeCoercion

Emitted when Psalm cannot be sure that part of an array/iterabble argument's type constraints can be fulfilled

class A {
    /** @var string[] */
    public $takesStringArray = [];
}

function foo(A $a, array $arr) : void {
    $a->takesStringArray = $arr;
}

MixedReturnStatement

Emitted when Psalm cannot determine the type of a given return statement

function foo() : int {
    return $_GET['foo']; // emitted here
}

MixedReturnTypeCoercion

Emitted when Psalm cannot be sure that part of an array/iterabble return type's constraints can be fulfilled

/**
 * @return string[]
 */
function foo(array $a) : array {
    return $a;
}

MixedStringOffsetAssignment

Emitted when assigning a value on a string using a value for which Psalm cannot infer a type

"hello"[0] = $_GET['foo'];

MoreSpecificImplementedParamType

Emitted when a class implements an interface method but a param type is less specific than the interface method param type

class A {}
class B extends A {
    public function bar(): void {}
}
class C extends A {
    public function bar(): void {}
}

class D {
    public function foo(A $a): void {}
}

class E extends D {
    /** @param B|C $a */
    public function foo(A $a): void {
        $a->bar();
    }
}

MoreSpecificReturnType

Emitted when the declared return type for a method is more specific than the inferred one (emitted in the same methods that LessSpecificReturnStatement is)

class A {}
class B extends A {}
function foo() : B {
    /** @psalm-suppress LessSpecificReturnStatement */
    return new A();
}

NoValue

Emitted when using the result of a function that never returns.

/**
 * @return never-returns
 */
function foo() : void {
    exit();
}

$a = foo();

NoInterfaceProperties

Emitted when trying to fetch a property on an interface as interfaces, by definition, do not have definitions for properties.

interface I {}
class A implements I {
    /** @var ?string */
    public $foo;
}
function bar(I $i) : void {
    if ($i->foo) {}
}

NonStaticSelfCall

Emitted when calling a non-static function statically

class A {
    public function foo(): void {}

    public static function bar(): void {
        self::foo();
    }
}

NullableReturnStatement

Emitted if a return statement contains a null value, but the function return type is not nullable

function foo() : string {
    if (rand(0, 1)) {
        return "foo";
    }

    return null; // emitted here
}

NullArgument

Emitted when calling a function with a null value argument when the function does not expect it

function foo(string $s) : void {}
foo(null);

NullArrayAccess

Emitted when trying to access an array value on null

$arr = null;
echo $arr[0];

NullArrayOffset

Emitted when trying to access an array offset with null

$arr = ['' => 5, 'foo' => 1];
echo $arr[null];

NullFunctionCall

Emitted when trying to use null as a callable

$arr = null;
echo $arr();

NullIterator

Emitted when iterating over null

foreach (null as $a) {}

NullOperand

Emitted when using null as part of an operation (e.g. +, ., ^ etc.)

echo null . 'hello';

NullPropertyAssignment

Emitted when trying to set a property on null

$a = null;
$a->foo = "bar";

NullPropertyFetch

Emitted when trying to fetch a property on a null value

$a = null;
echo $a->foo;

NullReference

Emitted when attempting to call a method on null

$a = null;
$a->foo();

OverriddenMethodAccess

Emitted when a method is less accessible than its parent

class A {
    public function foo() : void {}
}
class B extends A {
    protected function foo() : void {}
}

OverriddenPropertyAccess

Emitted when a property is less accessible than the same-named property in its parent class

class A {
    /** @var string|null */
    public $foo;
}
class B extends A {
    /** @var string|null */
    protected $foo;
}

ParadoxicalCondition

Emitted when a paradox is encountered in your programs logic that could not be caught by RedundantCondition

function foo($a) : void {
    if ($a) return;
    if ($a) echo "cannot happen";
}

ParentNotFound

Emitted when using parent:: in a class without a parent class.

class A {
  public function foo() : void {
    parent::foo();
  }
}

ParseError

Emitted when the PHP Parser encounters an error.

class A {
  public function foo() : void {
    echo "foo"
  }
}

PluginIssue

Can be emitted by plugins.

PossibleRawObjectIteration

Emitted when possibly iterating over an object’s properties, the comparison to RawObjectIteration.

class A {
    /** @var string|null */
    public $foo;

    /** @var string|null */
    public $bar;
}

function takesA(A $a) {
    if (rand(0, 1)) {
        $a = [1, 2, 3];
    }

    foreach ($a as $property) {}
}

PossiblyFalseArgument

Emitted when a function argument is possibly false, but the function doesn’t expect false. This is distinct from a function argument is possibly bool, which results in PossiblyInvalidArgument.

function foo(string $s) : void {
    $a_pos = strpos($s, "a");
    echo substr($s, $a_pos);
}

PossiblyFalseIterator

Emitted when trying to iterate over a value that may be false

$arr = rand(0, 1) ? [1, 2, 3] : false;
foreach ($arr as $a) {}

PossiblyFalseOperand

Emitted when using a possibly false value as part of an operation (e.g. +, ., ^ etc).

function foo(string $a) : void {
    echo strpos($a, ":") + 5;
}

PossiblyFalsePropertyAssignmentValue

Emitted when trying to assign a value that may be false to a property that only takes non-false values.

class A {
    /** @var int */
    public $foo = 0;
}

function assignToA(string $s) {
    $a = new A();
    $a->foo = strpos("haystack", $s);
}

PossiblyFalseReference

Emitted when making a method call on a value than might be false

class A {
    public function bar() : void {}
}

/** @return A|false */
function foo() {
    return rand(0, 1) ? new A : false;
}

foo()->bar();

PossiblyInvalidArgument

Emitted when

/** @return int|stdClass */
function foo() {
    return rand(0, 1) ? 5 : new stdClass;
}
function bar(int $i) : void {}
bar(foo());

PossiblyInvalidArrayAccess

Emitted when attempting to access an array offset on a value that may not be an array

$arr = rand(0, 1) ? 5 : [4, 3, 2, 1];
echo $arr[0];

PossiblyInvalidArrayAssignment

Emitted when attempting to assign an array offset on a value that may not be an array

$arr = rand(0, 1) ? 5 : [4, 3, 2, 1];
$arr[0] = "hello";

PossiblyInvalidCast

Emitted when attempting to cast a value that may not be castable

class A {}
class B {
    public function __toString() {
        return 'hello';
    }
}
$c = (string) (rand(0, 1) ? new A() : new B());

PossiblyInvalidArrayOffset

Emitted when it’s possible that the array offset is not applicable to the value you’re trying to access.

$arr = rand(0, 1) ? ["a" => 5] : "hello";
echo $arr[0];

PossiblyInvalidFunctionCall

Emitted when trying to call a function on a value that may not be callable

$a = rand(0, 1) ? 5 : function() : int { return 5; };
$b = $a();

PossiblyInvalidIterator

Emitted when trying to iterate over a value that may be invalid

$arr = rand(0, 1) ? [1, 2, 3] : "hello";
foreach ($arr as $a) {}

PossiblyInvalidMethodCall

Emitted when trying to call a method on a value that may not be an object

class A {
    public function bar() : void {}
}

/** @return A|int */
function foo() {
    return rand(0, 1) ? new A : 5;
}

foo()->bar();

PossiblyInvalidOperand

Emitted when using a possibly invalid value as part of an operation (e.g. +, ., ^ etc.

function foo() : void {
    $b = rand(0, 1) ? [] : 4;
    echo $b + 5;
}

PossiblyInvalidPropertyAssignment

Emitted when trying to assign a property on a value that may not be an object or may be an object that doesn’t have the desired property.

class A {
    /** @var ?string */
    public $bar;
}

/** @return A|int */
function foo() {
    return rand(0, 1) ? new A : 5;
}

$a = foo();
$a->bar = "5";

PossiblyInvalidPropertyAssignmentValue

Emitted when trying to assign a possibly invalid value to a typed property.

class A {
    /** @var int[] */
    public $bb = [];
}

class B {
    /** @var string[] */
    public $bb;
}

$c = rand(0, 1) ? new A : new B;
$c->bb = ["hello", "world"];

PossiblyInvalidPropertyFetch

Emitted when trying to fetch a property on a value that may not be an object or may be an object that doesn’t have the desired property.

class A {
    /** @var ?string */
    public $bar;
}

/** @return A|int */
function foo() {
    return rand(0, 1) ? new A : 5;
}

$a = foo();
echo $a->bar;

PossiblyNullArgument

Emitted when calling a function with a value that’s possibly null when the function does not expect it

function foo(string $s) : void {}
foo(rand(0, 1) ? "hello" : null);

PossiblyNullArrayAccess

Emitted when trying to access an array offset on a possibly null value

function foo(?array $a) : void {
    echo $a[0];
}

PossiblyNullArrayAssignment

Emitted when trying to set a value on a possibly null array

$a = null;
$a[0][] = 1;

PossiblyNullArrayOffset

Emitted when trying to access a value on an array using a possibly null offset

function foo(?int $a) : void {
    echo [1, 2, 3, 4][$a];
}

PossiblyNullFunctionCall

Emitted when trying to call a function on a value that may be null

function foo(?callable $a) : void {
    $a();
}

PossiblyNullIterator

Emitted when trying to iterate over a value that may be null

function foo(?array $arr) : void {
    foreach ($arr as $a) {}
}

PossiblyNullOperand

Emitted when using a possibly null value as part of an operation (e.g. +, ., ^ etc.)

function foo(?int $a) : void {
    echo $a + 5;
}

PossiblyNullPropertyAssignment

Emitted when trying to assign a property to a possibly null object

class A {
    /** @var ?string */
    public $foo;
}
function foo(?A $a) : void {
    $a->foo = "bar";
}

PossiblyNullPropertyAssignmentValue

Emitted when trying to assign a value that may be null to a property that only takes non-null values.

class A {
    /** @var string */
    public $foo = "bar";
}

function assignToA(?string $s) {
    $a = new A();
    $a->foo = $s;
}

PossiblyNullPropertyFetch

Emitted when trying to fetch a property on a possibly null object

class A {
    /** @var ?string */
    public $foo;
}
function foo(?A $a) : void {
    echo $a->foo;
}

PossiblyNullReference

Emitted when trying to call a method on a possibly null value

class A {
    public function bar() : void {}
}
function foo(?A $a) : void {
    $a->bar();
}

PossiblyUndefinedArrayOffset

Emitted when trying to access a possibly undefined array offset

if (rand(0, 1)) {
    $arr = ["a" => 1, "b" => 2];
} else {
    $arr = ["a" => 3];
}

echo $arr["b"];

PossiblyUndefinedGlobalVariable

Emitted when trying to access a variable in the global scope that may not be defined

if (rand(0, 1)) {
  $a = 5;
}
echo $a;

PossiblyUndefinedMethod

Emitted when trying to access a method that may not be defined on the object

class A {
    public function bar() : void {}
}
class B {}

$a = rand(0, 1) ? new A : new B;
$a->bar();

PossiblyUndefinedVariable

Emitted when trying to access a variable in function scope that may not be defined

function foo() : void {
    if (rand(0, 1)) {
        $a = 5;
    }
    echo $a;
}

PossiblyUnusedMethod

Emitted when --find-dead-code is turned on and Psalm cannot find any calls to a given class method

class A {
    public function foo() : void {}
    public function bar() : void {}
}
(new A)->foo();

PossiblyUnusedParam

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a particular parameter in a public/protected method

class A {
    public function foo(int $a, int $b) : int {
        return $a + 4;
    }
}

$a = new A();
$a->foo(1, 2);

PossiblyUnusedProperty

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a particular public/protected property

class A {
    /** @var string|null */
    public $foo;

    /** @var int|null */
    public $bar;
}

$a = new A();
echo $a->foo;

PropertyNotSetInConstructor

Emitted when a non-null property without a default value is declared but not set in the class’s constructor

class A {
    /** @var string */
    public $foo;

    public function __construct() {}
}

PropertyTypeCoercion

Emitted when setting a property with an value which has a less specific type than the property expects

class A {}
class B extends A {}

function takesA(C $c, A $a) : void {
    $c->b = $a;
}

class C {
    /** @var ?B */
    public $b;
}

RawObjectIteration

Emitted when iterating over an object’s properties. This issue exists because it may be undesired behaviour (e.g. you may have meant to iterate over an array)

class A {
    /** @var string|null */
    public $foo;

    /** @var string|null */
    public $bar;
}

function takesA(A $a) {
    foreach ($a as $property) {}
}

RedundantCondition

Emitted when conditional is redundant given previous assertions

class A {}
function foo(A $a) : ?A {
    if ($a) return $a;
    return null;
}

RedundantConditionGivenDocblockType

Emitted when conditional is redundant given information supplied in one or more docblocks.

This may be desired (e.g. when checking user input) so is distinct from RedundantCondition, which only applies to non-docblock types.

/**
 * @param string $s
 *
 * @return void
 */
function foo($s) {
    if (is_string($s)) {};
}

ReferenceConstraintViolation

Emitted when changing the type of a pass-by-reference variable

function foo(string &$a) {
    $a = 5;
}

ReservedWord

Emitted when using a reserved word as a class name

function foo(resource $res) : void {}

StringIncrement

Emitted when attempting to increment a string - this works in PHP, but is unexpected behaviour for most people.

$a = "hello";
$a++;

TaintedInput

Emitted when tainted input detection is turned on

TraitMethodSignatureMismatch

Emitted when a method's signature or return type differs from corresponding trait-defined method

trait T {
    abstract public function foo(int $i);
}

class A {
    use T;

    public function foo(string $s) : void {}
}

TooFewArguments

Emitted when calling a function with fewer arguments than the function has parameters

function foo(string $a) : void {}
foo();

TooManyArguments

Emitted when calling a function with more arguments than the function has parameters

function foo(string $a) : void {}
foo("hello", 4);

TooManyTemplateParams

Emitted when using the @extends/@implements annotation to extend a class and adds too many types.

/**
 * @template-implements IteratorAggregate<int, string, int>
 */
class SomeIterator implements IteratorAggregate
{
    public function getIterator() {
        yield 5;
    }
}

TypeDoesNotContainNull

Emitted when checking a non-nullable type for null

$a = "hello";
if ($a === null) {}

TypeDoesNotContainType

Emitted checking whether one value has a type or value that is impossible given its currently-known type

$a = "hello";
if ($a === 5) {}

UncaughtThrowInGlobalScope

Emitted when a possible exception isn't caught in global scope

/**
 * @throws \Exception
 */
function foo() : int {
    return random_int(0, 1);
}
foo();

UndefinedClass

Emitted when referencing a class that doesn’t exist

$a = new A();

UndefinedConstant

Emitted when referencing a constant that doesn’t exist

echo FOO_BAR;

UndefinedDocblockClass

Emitted when referencing a class that doesn’t exist from a docblock

/**
 * @param DoesNotExist $a
 */
function foo($a) : void {}

UndefinedFunction

Emitted when referencing a function that doesn't exist

foo();

UndefinedGlobalVariable

Emitted when referencing a variable that doesn't exist

echo $a;

UndefinedInterface

Emitted when referencing an interface that doesn’t exist but does have an identically-named class.

class C {}

interface I extends C {}

UndefinedMethod

Emitted when calling a method that doesn’t exist

class A {}
A::foo();

UndefinedInterfaceMethod

Emitted when calling a method that doesn’t exist on an interface

interface I {}

function foo(I $i) {
    $i->bar();
}

UndefinedPropertyAssignment

Emitted when assigning a property on an object that doesn’t have that property defined

class A {}
$a = new A();
$a->foo = "bar";

UndefinedPropertyFetch

Emitted when getting a property on an object that doesn’t have that property defined

class A {}
$a = new A();
echo $a->foo;

UndefinedThisPropertyAssignment

Emitted when assigning a property on an object in one of that object’s methods when no such property exists

class A {
    function foo() {
        $this->foo = "bar";
    }
}

UndefinedThisPropertyFetch

Emitted when getting a property for an object in one of that object’s methods when no such property exists

class A {
    function foo() {
        echo $this->foo;
    }
}

UndefinedTrait

Emitted when referencing a trait that doesn’t exist

class A {
    use T;
}

UndefinedVariable

Emitted when referencing a variable that doesn't exist in a given function’s scope

function foo() {
    echo $a;
}

UnevaluatedCode

Emitted when --find-dead-code is turned on and Psalm encounters code that will not be evaluated

function foo() : void {
    return;
    $a = "foo";
}

UnimplementedAbstractMethod

Emitted when a class extends another, but does not implement all of its abstract methods

abstract class A {
    abstract public function foo() : void;
}
class B extends A {}

UnimplementedInterfaceMethod

Emitted when a class implements an interface but does not implement all of its methods

interface I {
    public function foo() : void;
}
class A implements I {}

UninitializedProperty

Emitted when a property is used in a constructor before it is initialized

class A {
    /** @var string */
    public $foo;

    public function __construct() {
        echo strlen($this->foo);
        $this->foo = "foo";
    }
}

UnnecessaryVarAnnotation

Emitted when --find-dead-code is turned on and you're using a @var annotation on an assignment that Psalm has already identified a type for.

function foo() : string {
    return "hello";
}

/** @var string */
$a = foo();

UnrecognizedExpression

Emitted when Psalm encounters an expression that it doesn't know how to handle. This should never happen.

UnrecognizedStatement

Emitted when Psalm encounters a code construct that it doesn't know how to handle. This should never happen.

UnresolvableInclude

Emitted when Psalm cannot figure out what specific file is being included/required by PHP.

function requireFile(string $s) : void {
    require_once($s);
}

UnusedClass

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a given class

class A {}
class B {}
$a = new A();

UnusedMethod

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a given private method or function

class A {
    public function __construct() {
        $this->foo();
    }
    private function foo() : void {}
    private function bar() : void {}
}
$a = new A();

UnusedClosureParam

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a particular parameter in a closure.

$a = function (int $a, int $b) : int {
    return $a + 4;
};

/**
 * @param callable(int,int):int $c
 */
function foo(callable $c) : int {
    return $c(2, 4);
}

UnusedFunctionCall

Emitted when --find-dead-code is turned on and Psalm finds a function call whose return value is not used anywhere

$a = strlen("hello");
strlen("goodbye"); // unused
echo $a;

UnusedMethodCall

Emitted when --find-dead-code is turned on and Psalm finds a method call whose return value is not used anywhere

class A {
    private string $foo;

    public function __construct(string $foo) {
        $this->foo = $foo;
    }

    public function getFoo() : string {
        return $this->foo;
    }
}

$a = new A("hello");
$a->getFoo();

UnusedParam

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a particular parameter in a private method or function

function foo(int $a, int $b) : int {
    return $a + 4;
}

UnusedProperty

Emitted when --find-dead-code is turned on and Psalm cannot find any uses of a private property

class A {
    /** @var string|null */
    private $foo;

    /** @var int|null */
    private $bar;

    public function getFoo(): ?string {
        return $this->foo;
    }
}

$a = new A();
echo $a->getFoo();

UnusedPsalmSuppress

Emitted when --find-unused-psalm-suppress is turned on and Psalm cannot find any uses of a given @psalm-suppress annotation

/** @psalm-suppress InvalidArgument */
echo strpos("hello", "e");

UnusedVariable

Emitted when --find-dead-code is turned on and Psalm cannot find any references to a variable, once instantiated

function foo() : void {
    $a = 5;
    $b = 4;
    echo $b;
}