Problem with wall grabbing script

Hello, I want my wall grab script to grab onto a surface and stay in the correct orientation based on where the player grabbed it. I got this to work however when spinning around a circle, when reaching either the top or bottom of it my character would always turn 180 which looked unnatural. I think it might be because of gimbal lock but I’m not sure how to prevent that.

This is the part that controls the Character’s orientation and position.

local targetLookAt = CFrame.lookAt(ledgePart.Position, (ledgePart.CFrame * CFrame.new(0, 0, -1)).Position)
rootPart.CFrame = rootPart.CFrame:Lerp(targetLookAt, 1)

This is the whole function.

local function detectLedge()
	print("Function started")
	if vaultsleft > 0 and canVault and (humanoid:GetState() == Enum.HumanoidStateType.Freefall or humanoid:GetState() == Enum.HumanoidStateType.Jumping) then
		local vaultCheck = workspace:Raycast(rootPart.CFrame.Position, rootPart.CFrame.LookVector * 5, raycastParams)
		local AboveHeadCheck = workspace:Raycast(head.CFrame.Position, rootPart.CFrame.LookVector * 5, raycastParams)
		
		local headoverledge = false
		StopVault = false
		
		if not AboveHeadCheck then
			headoverledge = true
		end
		if vaultCheck then
			if vaultCheck.Instance then			
				local localPos = vaultCheck.Instance.CFrame:PointToObjectSpace(vaultCheck.Position)
				local yOffset
				local ledgePosition

				if not headoverledge then
					yOffset = 0
					ledgePosition = vaultCheck.Position + vaultCheck.Normal * 1 + Vector3.new(0, yOffset, 0)
				else
					yOffset = (vaultCheck.Instance.Size.Y / 2 - 2)
					
					local adjustedLocalPos = Vector3.new(localPos.X, yOffset, localPos.Z)
					ledgePosition = vaultCheck.Instance.CFrame:PointToWorldSpace(adjustedLocalPos) + vaultCheck.Normal * 1
				end

				local targetPos = ledgePosition - vaultCheck.Normal

				local magnitude = (ledgePosition - head.Position).Magnitude
					if magnitude < 5 then
						
					local dotProduct = rootPart.CFrame.LookVector:Dot(vaultCheck.Normal)
					if dotProduct > -0.9 then
						
						return
					end
						
					vaultsleft -= 1 -- START VAULT
					character:SetAttribute("WallGrab", true) 
					AniTrack:play()
						canVault = false
					
						ledgePart = Instance.new("Part")
						ledgePart.Parent = workspace
						ledgePart.Size = Vector3.one
						ledgePart.CFrame = CFrame.lookAt(ledgePosition, targetPos)
						ledgePart.CanQuery = false
						ledgePart.CanCollide = false
						ledgePart.CanTouch = false
						ledgePart.Transparency = 0
						
						local weldTarget = vaultCheck.Instance
						if weldTarget and weldTarget:IsA("BasePart") then
							local weld = Instance.new("WeldConstraint")
							weld.Part0 = ledgePart
							weld.Part1 = weldTarget
							weld.Parent = ledgePart
						end
							
						
					local starttime = tick()
					
					vaultConnection = RunService.RenderStepped:Connect(function(dt)
						
						local dotProduct = rootPart.CFrame.LookVector:Dot(vaultCheck.Normal)

						if tick() - starttime > 1000 or holdingS == true or CancelFlag == true then
							StopVault = true
						end
						
						if StopVault then
							print("Stopped")
							vaultConnection:Disconnect()
							canVault = true
							character:SetAttribute("WallGrab", false)
							AniTrack:Stop()
							rootPart.Anchored = false
							character:SetAttribute("CanRotate", true)

							if ledgePart then
								ledgePart:Destroy()
							end
						else
							rootPart.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
							rootPart.Anchored = true
							character:SetAttribute("CanRotate", false)

							local targetLookAt = CFrame.lookAt(ledgePart.Position, (ledgePart.CFrame * CFrame.new(0, 0, -1)).Position)
							rootPart.CFrame = rootPart.CFrame:Lerp(targetLookAt, 1)
							humanoid:ChangeState(Enum.HumanoidStateType.Seated)
						end
					end)
				end
			end
		end
	elseif canVault == false then
		canVault = true
		character:SetAttribute("WallGrab", false)
		AniTrack:Stop()
		character:SetAttribute("CanRotate", true)
		rootPart.Anchored = false
		humanoid:ChangeState(Enum.HumanoidStateType.Jumping)

		--check if it exists and then disconnect
		if vaultConnection then
			vaultConnection:Disconnect()
		end

		if ledgePart then
			ledgePart:Destroy()
		end
	end
end