I think that's because on the index you want an array of records, but on show you just want a single record.

When you pass in the array into policy_scope, it's going to call the .where(company_id: X) method on it. This works when you return Item.all but when you pass in just an Item record, that does not have a where method because it's a single instance of the Item class.

In your show action, you can change it to:

def show
@item = Item.find(params[:id])
authorize @item
end

And this will load the record and Pundit will know to authorize it against the right method in the policy without hitting the Scope.