Nil detector not working

I want to create a system where I can save quests with datastores. I have a loop that determines if any of the items in the quest are nil (for whatever reason). For some reason, however, it will output as if there are no nil values in the list, even though I receive a warning saying that a value that is meant to be a number is NIL. I asked the Roblox Assistant AI, and it told me to iterate using pairs(). I did, but the error persists.

	for i, quest in questData do --loop through each quest in questData
		local success, questContents = pcall(function() --try and get the contents of each quest in questData
			return questData[i]:GetAsync(player.UserId)
		end)
		
		local dataValid = true
		--THIS IS WHERE IT SHOULD FIND NILS
		for _, item in pairs(questContents) do
			if item == nil then
				dataValid = false
				break
			end	
		end
		
		if dataValid and success then
			print("it SHOULD be valid") --IT ISNT VALID
			
			local objective = questContents.Objective
		
			player["Quest" .. i].QuestObjective.Value = objective
			player["Quest" .. i].ObjectiveClass.Value = questContents.ObjectiveClass
			
			player["Quest" .. i].QuestProgress.Value = questContents.QuestProgress
			player["Quest" .. i].UseCredits.Value = questContents.UseCredits

		else
			local randomQuest = TasksModule:GenerateQuest()
			
			print(randomQuest:GetUsableText())
			player["Quest" .. i].QuestObjective.Value = randomQuest.Objective
			player["Quest" .. i].ObjectiveClass.Value = randomQuest.ObjectiveClass
			
			player["Quest" .. i].UseCredits.Value = randomQuest.UseCredits
		end
	end	

To be honest, this code is very weird, and it keeps spewing errors that I for the life of me cannot fix.

I don’t really understand your perspective, but the way tables work is that if a value is nil in said table, it just doesn’t exist. I’m not talking memory-wise here, but simply accessibility.

print(someTable.Value) -- nil

The value simply isn’t there, so it prints nil. Nil values cannot be picked up by iterators, because it wouldn’t make sense, it would loop forever.

The issue here is that pairs() won’t catch missing keys. If a key in your table doesn’t exist at all, it just gets skipped. That’s why your loop isn’t finding the nils.

Instead of looping, you should explicitly check for the keys you expect , like:

if not questContents.Objective or not questContents.ObjectiveClass or not questContents.QuestProgress then
    dataValid = false
end

This way you’re checking the structure and not just the values that exist. Missing fields won’t be silently ignored. Also, make sure questContents is actually a table before trying to access anything.