Framework activity
Debug Gates, policies, and denied requests
When a request is denied, inspect the decision in the context that produced it. The user, resource, and resolved handler matter as much as the result.
Find the decision behind the response
Select the request that returned the unexpected result, then open Authorization. Filter to denied decisions if that matches the symptom. Open the ability you expected the action to check.
Read the evaluated user and arguments. A missing user, a different model instance, or the wrong guard can explain a result before you reach the policy method.
Check the resolved policy or Gate
The detail shows the policy or Gate handler when it can be resolved, its application source, and available decision messages, codes, or custom response status. Open the policy method and compare its inputs with the captured user and resource.
A policy like this allows the owner to update a trip:
public function update(User $user, Trip $trip): bool
{
return $trip->user_id === $user->id;
}
Check ownership and the rule you intended to enforce. If the resolved method looks right but the result still differs, inspect Gate or policy before/after hooks. The inspector does not identify every hook that may affect the final decision.
Compare the same ability with two users
In an existing app with a Trip policy, load the owner and another fixture user, then check the same resource:
use Illuminate\Support\Facades\Gate;
$ownerDecision = Gate::forUser($owner)->inspect('update', $trip);
$otherDecision = Gate::forUser($otherUser)->inspect('update', $trip);
expect($ownerDecision->allowed())->toBeTrue();
expect($otherDecision->allowed())->toBeFalse();
These are test assertions for a rule that permits only the owner. Adapt the expected decisions to your actual policy. Then exercise the HTTP route separately: a policy check in a unit of code does not prove the route calls it.
Trace checks inside Blade
Repeated @can checks can come from a list or a shared component. Use the retained source to find the original Blade template when it is available. Confirm which resource each row passed to the ability before changing repeated checks.
Authorization and authentication answer different questions. Use Requests to check the matched route, guard, and authentication context.
Verify allowed and denied behavior
- Repeat the failing action as the intended user and resource.
- Check the recorded decision and the real response, including any custom denial status.
- Add a focused route test for the allowed case and a denied case.
- Keep the denial when the policy correctly protects the action.
See Laravel’s authorization documentation for the framework’s Gate and policy behavior.
Next step
Inspect form validation
A handled validation failure can explain why a form never reaches the authorized action.
Read the guide