livewire/livewire: Revert "[4.x] Support exception hook for computed properties"
Contributed by calebporzio
Part of the livewire v4.4.7 release
Pull request #10609 reverts #10543 ("[4.x] Support exception hook for computed properties"), which had briefly made exceptions thrown inside #[Computed] methods flow into a component's exception() hook. With this revert, a throwable raised during computed-property evaluation once again propagates through Laravel's standard exception handling instead of being routed to the component hook. If you are upgrading from v3.8.10, this restores the observable behavior you already depend on — the change only matters if you experimented with recent v4 builds that included the short-lived feature.
What changed
The revert is small and surgical. In src/Features/SupportComputed/BaseComputed.php, the internal evaluateComputed() method — the code path that actually invokes your #[Computed] method — had been changed to run the call through Livewire's exception-aware wrap() helper, so a thrown exception would be captured and forwarded to the component's exception($e, $stopPropagation) hook. PR #10609 restores the direct invocation and drops the now-unused wrap import:
// Briefly in v4 (PR #10543) — now reverted
protected function evaluateComputed()
{
$value = null;
wrap($this->component)->tap(function ($component) use (&$value) {
$value = invade($component)->{parent::getName()}();
});
return $value;
}
// Restored by PR #10609
protected function evaluateComputed()
{
return invade($this->component)->{parent::getName()}();
}
The accompanying unit test, test_computed_attribute_can_trigger_component_exception_hook, and its private ComputedPropertyException helper class were deleted as well, since they existed only to verify the reverted behavior. Nothing about the public #[Computed] attribute API changes.
Why it was reverted
Livewire components can define an exception() method that the framework calls when a throwable surfaces during a request, letting you swallow, log, or transform errors before they reach Laravel's handler. PR #10543 extended that safety net to computed properties. While convenient in isolation, the implementation wrapped every computed-property evaluation in the exception-handling pipeline — altering the execution path for the feature's hottest code just to accommodate the error case. It also introduced an inconsistency: exceptions from actions and render were handled by one mechanism, while exceptions from computed properties took a different route. The maintainers evidently decided the trade-off wasn't worth it and pulled the feature before it could stabilize in a v4 release, returning to the long-standing, well-understood behavior.
What this means for your computed properties
An exception thrown inside a computed property now behaves like any other uncaught exception: it bubbles up and is reported and handled by Laravel's exception handler. The component's exception() hook will not fire:
use Livewire\Attributes\Computed;
class InvoiceReport extends Component
{
#[Computed]
public function total(): int
{
// If this throws, it will NOT reach exception() below.
return $this->paymentGateway->grandTotal();
}
public function exception($e, $stopPropagation)
{
// Still fires for exceptions in actions and render,
// but never for computed property exceptions.
}
}
If you need graceful handling for a computed property, wrap the logic inside the method itself:
#[Computed]
public function total(): int
{
try {
return $this->paymentGateway->grandTotal();
} catch (GatewayException $e) {
report($e);
return 0; // sensible fallback
}
}
This keeps failure handling local and explicit, without depending on Livewire's hook plumbing.
Upgrade impact
For anyone coming from v3.8.10, this is good news in the most boring way possible: v3.8.10 never routed computed-property exceptions through the hook, so v4 now matches the behavior you already rely on. There is nothing to migrate and no configuration to change. The one group that needs to act is teams that installed an intermediate v4 build, noticed the hook firing for computed properties, and wrote handling code around it — that code will now silently stop executing. Search your components for exception( methods with branches that expect computed-property exceptions, and either delete those branches or replace them with a try/catch inside the computed method. If you subclassed or extended the computed internals directly (rare), the evaluateComputed() signature is unchanged.
Takeaways
- PR #10609 reverts #10543: exceptions thrown inside
#[Computed]methods no longer trigger the component'sexception()hook in v4. - Upgrading from v3.8.10? The observable behavior is the same as what you had — no action required.
- If you relied on the hook behavior from a v4 pre-release, handle errors with try/catch inside the computed method instead.
- Uncaught computed-property exceptions now propagate normally to Laravel's exception handler, exactly as they did throughout v3.