People searching “Laravel viewAny Vue” call authorize('view', $post) on the index and then the index has no post to pass. viewAny is the index check. view is one row. The policy guide is the class. The CRUD guide is the list.
TL;DR
- viewAny takes the model class, not a row.
- Call it on the index before you paginate.
- Do not filter the rows in Vue after sending every post to the browser.
The fix#
public function viewAny(User $user): bool
{
return $user->can('posts.view');
}
public function index(Request $request): Response
{
$this->authorize('viewAny', Post::class);
return Inertia::render('posts/Index', [
'posts' => Post::query()->latest('id')->paginate(12),
]);
}The second argument is the class. An instance would call view, not viewAny.
What to avoid#
Gotcha
Do not filter the rows in Vue after sending every post to the browser. If the user may only see their own, scope the query as well as the gate. The gate answers “may this person open the index?”. The query answers “which rows?”.
FAQ#
How do I gate a Vue index with viewAny?
viewAny takes the model class, not a row. Call it on the index before you paginate.
What goes wrong with Laravel viewAny Vue?
Many developers call authorize('view', $post) on the index and then the index has no post to pass. Do not filter the rows in Vue after sending every post to the browser.



