PHPStan / Psalm Level Failures in CI - Stricter Analysis Breaks the Build
PHPStan (level 0–9/max) and Psalm (errorLevel 1–8) report type errors up to a configured strictness. Raising the level, upgrading the tool, or upgrading a dependency’s stubs surfaces new errors that fail the analysis step.
What this error means
A static-analysis CI step that passed before now reports type errors - often after bumping the PHPStan level/Psalm errorLevel, the tool version, or a dependency. The errors are deterministic and reproduce locally.
------ -----------------------------------------------------------------
Line src/OrderService.php
------ -----------------------------------------------------------------
42 Parameter #1 $id of method Repo::find() expects int, string given.
------ -----------------------------------------------------------------
[ERROR] Found 1 errorCommon causes
A higher level enables stricter rules
Each PHPStan level / Psalm errorLevel turns on more checks. Code that was clean at the old level now reports real type issues at the new one.
A tool or dependency upgrade added findings
Newer analyzer versions or updated stubs detect issues the previous version missed, so the same code suddenly fails.
How to fix it
Fix the reported type issues
Address each error - correct the type, add a guard, or annotate honestly.
# run locally to reproduce exactly
vendor/bin/phpstan analyse --level=8 src
vendor/bin/psalm --show-info=falseBaseline pre-existing errors when raising a level
Capture the current findings so only new issues fail, then burn the baseline down over time.
vendor/bin/phpstan analyse --generate-baseline
# Psalm
vendor/bin/psalm --set-baseline=psalm-baseline.xmlChange the level deliberately
- Pin the analyzer version so the level’s meaning is stable.
- Raise
level/errorLevelone step at a time, fixing or baselining as you go. - Keep the config committed so CI and local agree.
How to prevent it
- Pin the PHPStan/Psalm version so analysis is reproducible.
- Raise strictness incrementally with a shrinking baseline.
- Run the analyzer in CI on every PR to catch regressions early.