pestphp/pest · error · AssertionFailedError
Cached failure
Error message
Cached failure
What it means
With test-influence analysis (--tia), Pest caches per-test results and, on later runs, replays the cached verdict for tests unaffected by your changes instead of re-executing them. When the cached status resolves to ReplayType::Failure, Pest rethrows an AssertionFailedError carrying the stored failure message; if that stored message is empty it falls back to the literal text 'Cached failure'. Hitting it means a previously failing test was replayed from the TIA graph, so the test did not actually run this time.
Source
Thrown at src/Concerns/Testable.php:219
self::$__latestNotes = $method->notes;
self::$__latestIssues = $method->issues;
self::$__latestPrs = $method->prs;
/** @var Tia $tia */
$tia = Container::getInstance()->get(Tia::class);
$status = $tia->getStatus(self::$__filename, $this->valueObjectForEvents()->id());
$replay = ReplayType::fromStatus($status);
if ($replay !== ReplayType::None) {
assert($status !== null);
$this->__replay = $replay;
match ($replay) {
ReplayType::Pass, ReplayType::Risky => $this->__beginReplay($replay, $tia),
ReplayType::Skipped => $this->markTestSkipped($status->message()),
ReplayType::Incomplete => $this->markTestIncomplete($status->message()),
ReplayType::Failure => throw new AssertionFailedError($status->message() ?: 'Cached failure'),
};
return;
}
$recorder = Container::getInstance()->get(Recorder::class);
assert($recorder instanceof Recorder);
if ($recorder->isActive()) {
$recorder->beginTest($this::class, $this->name(), self::$__filename);
}
parent::setUp();
Collectors::armAll($recorder);
$beforeEach = TestSuite::getInstance()->beforeEach->get(self::$__filename)[1];
View on GitHub (pinned to 1af74a215c)
Solutions
- Re-run the same test without --tia (or delete the TIA cache) to execute the test for real and get the full failure output.
- Treat the cached verdict as genuine: fix the underlying failing test, then let the next --tia run record a passing status.
- If the cache is stale or suspicious (e.g., after a big rebase), clear the TIA cache directory so the next run records fresh statuses.
Example fix
# before vendor/bin/pest --tia # replays: 'Cached failure' with no diff # after vendor/bin/pest tests/Unit/ThatTest.php # real run, full diff rm -rf .pest # or clear the tia cache to force fresh recording
Defensive patterns
Strategy: retry
Prevention
- Treat any 'Cached failure' as a real failure: fix the test, don't try to suppress the replay.
- Clear the TIA cache after branch switches, rebases, or dependency updates so stale verdicts cannot replay.
- When a cached failure lacks a diff, re-run the exact test without --tia to see the real output before debugging.
When it happens
Trigger: Running vendor/bin/pest --tia after an earlier failing run, then editing files the TIA graph considers unrelated to that test; a failure status recorded without a message (empty diff/message in the cache), producing the 'Cached failure' default text; a stale TIA cache left over from before a branch switch.
Common situations: Teams enabling TIA to speed up large suites; CI or local caches (.pest tia graph) surviving branch switches or force-pushes; debugging confusion because the failure output shows no diff — only the cached message.
Related errors
- Expecting %s not %s %s.
- The test directory [%s] does not exist.
- The test expects [%d] argument(s), but the dataset only prov
- Expectation value is not iterable.
- No sequence expectations defined.
AI-assisted analysis of pestphp/pest@1af74a215c (2026-08-21).
Data as JSON: /api/errors/5a63fdfa50f2f59c.
Report an issue: GitHub.