Viewports not working sometimes

I’m trying to make a pet system, part of this is using viewports to give a preview of the pet, I have a module script to setup a viewport with a given pet, this has worked so far but sometimes it doesn’t and I don’t know why.

I also added a refresh button to reload all the viewports, but that didn’t work. It isn’t that efficient but it worked.

Gifs
https://gyazo.com/542f3cb57383e88872bc5ac18c5d870f

Code
PetViewport

--[[
DevTops
puts the valid stuff into a viewport to make it a pet thingy idk just trust me dude
]]

local replicatedStorage = game:GetService("ReplicatedStorage")

local pets = replicatedStorage:WaitForChild("Pets")

local PV = {}

function PV.setup(viewport, petName, folder)
	folder:ClearAllChildren()
	if not pets:FindFirstChild(petName) then return end
	local clonedPet = pets:FindFirstChild(petName):Clone()
	local camera = Instance.new("Camera", viewport)
	viewport.CurrentCamera = camera
	clonedPet.Parent = folder
	local primPart = clonedPet.PrimaryPart	
	local _, size = clonedPet:GetBoundingBox()
	camera.CFrame = CFrame.new((primPart.CFrame - Vector3.new(size.X + 1, 0, 0)).Position, primPart.CFrame.Position)
	spawn(function()
		game:GetService("RunService").RenderStepped:Connect(function()
			if not clonedPet.PrimaryPart then return end
			clonedPet:SetPrimaryPartCFrame(clonedPet:GetPrimaryPartCFrame() * CFrame.fromEulerAnglesXYZ(0, 0.025, 0))
		end)
	end)
end

return PV

LoadPets - Loads pets from the player’s pets into UI elements the user can interact with

local petAdder = require(script.Parent:WaitForChild("PetAdder"))
local petsList = script.Parent:WaitForChild("Pets"):WaitForChild("Pets")
local player = game.Players.LocalPlayer
local data = player:WaitForChild("data")
local pets = data:WaitForChild("pets")
local equipedPets = data:WaitForChild("equipedPets")
local selectedPetValue = script.Parent:WaitForChild("SelectedFrame"):WaitForChild("Pet")
local gamepasses = player:WaitForChild("gamepasses")
local refresh = script.Parent:WaitForChild("Refresh"):WaitForChild("Button")

local replicatedStorage = game:GetService("ReplicatedStorage")
local modules = replicatedStorage:WaitForChild("Modules")
local equations = require(modules:WaitForChild("Equations"))
local purchaseLib = require(modules:WaitForChild("PurchaseLib"))

local genericButton = require(script.Parent.Parent.Parent:WaitForChild("GenericButton"))
genericButton.hook(refresh)

local infPetEquip = purchaseLib.api.getFromName("InfPetsEquipped")
local infPetStorage = purchaseLib.api.getFromName("InfPetsStorage")

local function loadAll()
	petsList.CanvasSize = UDim2.fromScale(1, 0)
	local function addSize() petsList.CanvasSize += UDim2.fromOffset(0, 20) end
	local amountOfPets = #pets:GetChildren() + #equipedPets:GetChildren()
	for _, child in pairs(petsList:GetChildren()) do if child:IsA("Frame") then child:Destroy() end end
	for _, pet in pairs(pets:GetChildren()) do petAdder.addPet(pet.Value); addSize(); end
	for _, pet in pairs(equipedPets:GetChildren()) do petAdder.addPet(pet.Value, true); addSize(); end
end

loadAll()
pets.ChildAdded:Connect(loadAll)
pets.ChildRemoved:Connect(loadAll)
equipedPets.ChildAdded:Connect(loadAll)
equipedPets.ChildRemoved:Connect(loadAll)
refresh.MouseButton1Click:Connect(loadAll)

PetAdder - Take a pet and makes a UI element with it

local replicatedStorage = game:GetService("ReplicatedStorage")
local pets = replicatedStorage:WaitForChild("Pets")
local petList = script.Parent:WaitForChild("Pets"):WaitForChild("Pets")
local selectedPetValue = script.Parent:WaitForChild("SelectedFrame"):WaitForChild("Pet")
local equipButton = script.Parent:WaitForChild("SelectedFrame"):WaitForChild("EquipButton"):WaitForChild("Button")

local modules = replicatedStorage:WaitForChild("Modules")
local petViewport = require(modules:WaitForChild("PetViewport"))

local petPrefab = script:WaitForChild("PetPrefab")

local PA = {}

function PA.addPet(petObject, equiped)
	equiped = equiped or false
	if type(petObject) == "string" then petObject = pets:WaitForChild(petObject) end
	local clonedPrefab = petPrefab:Clone()
	local petImage = clonedPrefab:WaitForChild("PetImage")
	local selectButton = clonedPrefab:WaitForChild("Button")
	local petName = clonedPrefab:WaitForChild("PetName")
	petViewport.setup(petImage, petObject.Name, petImage:WaitForChild("Dispose"))
	if equiped then petImage.ImageColor3 = Color3.fromRGB(0, 255, 0); clonedPrefab.LayoutOrder = 0; end
	clonedPrefab.Parent = petList
	petName.Text = petObject.Name
	selectButton.MouseButton1Click:Connect(function()
		if selectedPetValue.Value ~= petObject then selectedPetValue.Value = petObject else selectedPetValue.Value = nil end
	end)
	local function updateSelectedPet() if selectedPetValue.Value == petObject then petName.Font = Enum.Font.ArialBold else petName.Font = Enum.Font.Cartoon end end
	selectedPetValue.Changed:Connect(updateSelectedPet)
	updateSelectedPet()
	if selectedPetValue.Value == petObject then selectedPetValue.Value = nil; selectedPetValue.Value = petObject; end
	return clonedPrefab
end

function PA.removePet(petObject)
	if type(petObject) == "userdata" then petObject = petObject.Name end
	local found = petList:FindFirstChild(petObject)
	if not found then return end
	found:Destroy()
end

return PA

If I missed anything lmk but I’ve been confused by this for about 30 minutes