DataStore Length of Field Error

Hello!

I have a DataStore devoted to my BoolValues that up until tonight, worked fine. Tonight I suddenly started getting an error:

00:23:10.622 - BoolDataStore:42: attempt to get length of field ‘tbl_1’ (a nil value)
00:23:10.623 - Stack Begin
00:23:10.623 - Script ‘ServerScriptStorage.ToolsDataStore’, Line 42 - global loadData
00:23:10.624 - Script ‘ServerScriptStorage.ToolsDataStore’, Line 90
00:23:10.624 - Stack End

I’m not sure why that error is appearing or what it means, when it didn’t appear before. I’ve tried changing things, without it seeming to make a difference. I’ve reverted back to when it last worked/started giving that error.

The line that errors is: for x = 1, #data.tbl_1 do

I’ve marked where the error occurs in the script below with "-- THIS IS THE LINE THAT ERRORS. Any assistance on sorting this out would be very much appreciated! :slight_smile:

Module Script inside ServerScriptService:

local module = {}
local DataStoreService = game:GetService("DataStoreService")
local InventoryItems = DataStoreService:GetDataStore("XXXX")
local ToolGiverCheck = require(script.InvGiverCheck)
datastore_success = {}
hasValues = require(script.HasValues)

AUTOSAVE_INTERVAL = 120
DATASTORE_RETRIES = 3
function createData()
	local data = {}
	data.tbl_1 = {}
	data.tbl_2 = {}
	for x = 1, #hasValues do
		table.insert(data.tbl_1, hasValues[x])
		data[hasValues[x]] = false
	end
	return data
end
function dataStoreAttempt(dataStoreFunction)
	local tries = 0
	local success = false
	local data = nil
	repeat
		tries = tries + 1
		success = pcall(function() data = dataStoreFunction() end)
		if not success then wait(1) end
	until tries == DATASTORE_RETRIES or success
	return success, data
end
function loadData(Player)
	local Key = "PlayerIdNum-"..Player.UserId.."XXXXX"
	local InvData = Player:WaitForChild("Inventory")
	local success, data = dataStoreAttempt(function()
		 return InventoryItems:GetAsync(Key)
	end)
	if success then
		if not data then
			data = createData()
			print("Inventory new data successfully created for player '" .. Player.Name .. "'  (" .. Player.UserId .. ")")
		else
			for x = 1, #data.tbl_1 do -- THIS IS THE LINE THAT ERRORS
				local value = data.tbl_1[x]
				local inv_value = InvData:WaitForChild(value)
				inv_value.Value = data.tbl_2[value]
			end
				
			print("Inventory data successfully loaded for player '" .. Player.Name .. "'  (" .. Player.UserId .. ")")
		end
		datastore_success["id_"..Player.UserId] = true
	else
		print("Inventory data FAILED to load for player '" .. Player.Name .. "'  (" .. Player.UserId .. ")")
	end
end

function saveData(Player)
	if datastore_success["id_"..Player.UserId] then
		local Key = "PlayerIdNum-"..Player.UserId.."XXXXX"
		local InvData = Player:WaitForChild("Inventory")
		local data = createData()
		for x = 1, #data.tbl_1 do
			local value = data.tbl_1[x]
			local inv_value = InvData:WaitForChild(value)
			data.tbl_2[value] = inv_value.Value
		end
		
		local success, data = dataStoreAttempt(function()
			InventoryItems:SetAsync(Key, data)
		end)
		
		if not success then
			print("Inventory data FAILED to save for player '" .. Player.Name .. "'  (" .. Player.UserId .. ")")
		else
			print("Inventory data successfully saved for player '" .. Player.Name .. "'  (" .. Player.UserId .. ")")
		end
	end
end

game.Players.PlayerAdded:Connect(function(Player) -- Inventory
	local tnew = Instance.new
	local ts = tnew("Folder")
	ts.Name = "Inventory"
	ts.Parent = Player
	for x = 1, #hasValues do
		local tool = tnew("BoolValue")
		tool.Name = hasValues[x]
		tool.Value = false
		tool.Parent = ts
	end
	loadData(Player)
	repeat wait() until Player.Character
end)

game.Players.PlayerRemoving:Connect(function(Player)
	saveData(Player)
	datastore_success["id_"..Player.UserId] = nil
end)
 
spawn(function()
    while wait(AUTOSAVE_INTERVAL) do
        for i, Player in pairs (game:GetService("Players"):GetChildren()) do
            print("Inventory data Auto-saving for " .. Player.Name .. " .")
			saveData(Player)
        end
    end
end)


return module

Thank you again!

Hey. It seems that the saved data doesn’t contain the tbl_1 object so you can’t fetch it’s length. Try deleting your save manually or changing the datastore key to wipe previous saves.

You may also want to check what data are really saved. You may do this with printing the data like

print(game.HttpService:JSONEncode(data))
3 Likes

Datastores can return nil value if you didn’t save anything onto them yet.
You should have few case scenarios when loading data:

  1. Player is playing for the first time (no data)
  2. Player has played before (data exists)
  3. Datastore errored
1 Like

That did the trick and now all is well again! :smiley: Thank you!

1 Like

Hey! Just for you to know next time. This guy has clearly checked if data is not nil with

if not data then
-- NEW DATA
else
-- LOAD
end

So this could not be the issue. :grinning:
If you mean that the OP has to handle these cases - you’re clearly right, but it seems that he already does so it is a bit unrelated.

Yeah, I’ve inspected the code beforehand, figured I’d mention all three to be clear(er).