Value Level not being saved to datastore

Hey, I’ve got a Data Store which should be saving the value level, But it’s throwing up the error, “value of type nil cannot be converted to a number - Server - Minutes/Cash:50” This is line 50 - Level.Value = Data.Level

--[ SERVICES ]--

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TimeStats")
local service = game:GetService("MarketplaceService")


--[ LOCALS ]--

local VIPGamepassId = 853207256 -- VIP GAMEPASS ID
local GamepassId = 853079507  -- GAMEPASS ID


--[ FUNCTIONS ]--

game.Players.PlayerAdded:Connect(function(Player)
	

	--[{ LEADERSTATS }]--

    local Leaderstats = Instance.new("Folder")
    Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player
	
	local Level = Instance.new("IntValue")
	Level.Name = "Level" -- changing name here (points, levels, time, etc.)
	Level.Value = 0 -- default value
	Level.Parent = Leaderstats
	
	local Cash = Instance.new("IntValue")
	Cash.Name = "Cash" -- changing name here (points, levels, time, etc.)
	Cash.Value = 0 -- default value
	Cash.Parent = Player
	
	
	--[{ DATA STORE }]--
	
	
	local Data
	pcall(function()
		Data = DataStore:GetAsync(Player.UserId) -- Get Data 
		print(Player, "loading data")
	end)
	
	if type(Data) ~= "table" then
		Data = nil
	end
	
	if Data then
		Level.Value = Data.Level
		Cash.Value = Data.Cash
	end
	
	local incrementValue = 1 -- value when adding points

	if (service:UserOwnsGamePassAsync(Player.UserId, VIPGamepassId)) then -- 3x gamepass
		incrementValue = 3
	elseif (service:UserOwnsGamePassAsync(Player.UserId, GamepassId)) then -- 2x gamepass
		incrementValue = 2
	end
	

	--[{ TIME GIVERS }]--
	
	
	coroutine.resume(coroutine.create(function() -- gives 1 point every minute
		while true do
			wait(60) -- every minute
			Level.Value = Level.Value + incrementValue --  adds points based off of the incrementValue
		end
	end))
	
	coroutine.resume(coroutine.create(function() -- gives 1 point every minute
		while true do
			wait(120) -- every 2 minutes
			Cash.Value = Cash.Value + incrementValue -- adds cash
		end
	end))
	
	
end)




game.Players.PlayerRemoving:Connect(function(Player) -- save function here
	
	--[{ DATA STORE SAVING }]--
	
	DataStore:SetAsync(Player.UserId, { -- gets data
		Level = Player.leaderstats.Level.Value,
	})
	
end)

Any help will be greatly appreciated

1 Like

I’m not exactly sure if this was the issue, but it seems to be that your pcall sets the value of Data, though in LuaU pcalls aren’t yielded.

1 Like

You should change this to:

	if Data and Data.Level then
1 Like

Here’s a fixed version, that waits for the pcall

--[ SERVICES ]--

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TimeStats")
local service = game:GetService("MarketplaceService")


--[ LOCALS ]--

local VIPGamepassId = 853207256 -- VIP GAMEPASS ID
local GamepassId = 853079507  -- GAMEPASS ID


--[ FUNCTIONS ]--

game.Players.PlayerAdded:Connect(function(Player)


	--[{ LEADERSTATS }]--

	local Leaderstats = Instance.new("Folder")
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player

	local Level = Instance.new("IntValue")
	Level.Name = "Level" -- changing name here (points, levels, time, etc.)
	Level.Value = 0 -- default value
	Level.Parent = Leaderstats

	local Cash = Instance.new("IntValue")
	Cash.Name = "Cash" -- changing name here (points, levels, time, etc.)
	Cash.Value = 0 -- default value
	Cash.Parent = Player


	--[{ DATA STORE }]--


	local success, Data = pcall(function()
		 -- Get Data 
		print(Player, "loading data")
		return DataStore:GetAsync(Player.UserId)
	end)

	if success then
		
		if next(Data) == nil then
			Data = nil
		end
		
		if Data and (Data.Level and Data.Cash) then
			Level.Value = Data.Level
			Cash.Value = Data.Cash
		end
	end



	local incrementValue = 1 -- value when adding points

	if (service:UserOwnsGamePassAsync(Player.UserId, VIPGamepassId)) then -- 3x gamepass
		incrementValue = 3
	elseif (service:UserOwnsGamePassAsync(Player.UserId, GamepassId)) then -- 2x gamepass
		incrementValue = 2
	end


	--[{ TIME GIVERS }]--


	coroutine.resume(coroutine.create(function() -- gives 1 point every minute
		while true do
			wait(60) -- every minute
			Level.Value = Level.Value + incrementValue --  adds points based off of the incrementValue
		end
	end))

	coroutine.resume(coroutine.create(function() -- gives 1 point every minute
		while true do
			wait(120) -- every 2 minutes
			Cash.Value = Cash.Value + incrementValue -- adds cash
		end
	end))


end)




game.Players.PlayerRemoving:Connect(function(Player) -- save function here

	--[{ DATA STORE SAVING }]--

	DataStore:SetAsync(Player.UserId, { -- gets data
		Level = Player.leaderstats.Level.Value,
	})

end)
1 Like

This is not a solution to your problem, but I highly recommend using a datastore module such as Suphi’s Datastore Module or ProfileService in order to avoid data loss and other issues that come with Roblox’s default datastore system.

1 Like

@RiccoMiller is also right, you should check for Data.Level, because it could be nil.

2 Likes

I updated this, just recently to include and (Data.Level and Data.Cash), this will ensure the values are not nil, so the error cannot occur.

2 Likes

Ah, thank you for your help, It seems to be saving the data now.

:+1: Have a blessed day, however don’t forget to check Data.Level and Data.Cash before setting .Value since if they are nil then you will get this warning: value of type nil cannot be converted to a number.

1 Like

Yeah, It is throwing up that error in output, I’ll check them now

1 Like

How easy is it for me to switch over to say Suphi’s Datastore Module?

If you look at Suphi’s youtube video on the module it should be fairly easy to understand and switch your game to work with the module, but if you are a beginner and your game already has players/people with progress I would not recommend doing this as you would need to switch over all their data to work with the module.

1 Like

The game hasn’t been released yet, I’ll go have a look at their youtube video, Thanks for the reply.

1 Like

Apologies, But I seem to be making short work of this,

I tried, but I am unsure what needs to be changed with this script to update it from the old to new, I’ve watched the video but still abit confused,

--[ SERVICES ]--

local DataStoreModule = require(game.ServerStorage.DataStore2)
local service = game:GetService("MarketplaceService")


--[ LOCALS ]--

local VIPGamepassId = 853207256 -- VIP GAMEPASS ID
local GamepassId = 853079507  -- GAMEPASS ID


--[ FUNCTIONS ]--

game.Players.PlayerAdded:Connect(function(Player)


	--[{ LEADERSTATS }]--
	
	local keys = {"Level"}

	local Leaderstats = Instance.new("Folder")
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player

	local Level = Instance.new("IntValue")
	Level.Name = "Level" -- changing name here (points, levels, time, etc.)
	Level.Value = 0 -- default value
	Level.Parent = Leaderstats

	local Cash = Instance.new("IntValue")
	Cash.Name = "Cash" -- changing name here (points, levels, time, etc.)
	Cash.Value = 0 -- default value
	Cash.Parent = Player


	--[{ DATA STORE }]--


	local success, Data = pcall(function()
		-- Get Data 
		print(Player, "loading data")
		return DataStoreModule:GetAsync(Player.UserId)
	end)

	if success then

		if next(Data) == nil then
			Data = 0
		end

		if Data and Data.Level then
			Level.Value = Data.Level
			Cash.Value = Data.Cash
		end
	end



	local incrementValue = 1 -- value when adding points

	if (service:UserOwnsGamePassAsync(Player.UserId, VIPGamepassId)) then -- 3x gamepass
		incrementValue = 3
	elseif (service:UserOwnsGamePassAsync(Player.UserId, GamepassId)) then -- 2x gamepass
		incrementValue = 2
	end


	--[{ TIME GIVERS }]--


	coroutine.resume(coroutine.create(function() -- gives 1 point every minute
		while true do
			wait(60) -- every minute
			Level.Value = Level.Value + incrementValue --  adds points based off of the incrementValue
		end
	end))

	coroutine.resume(coroutine.create(function() -- gives 1 point every minute
		while true do
			wait(120) -- every 2 minutes
			Cash.Value = Cash.Value + incrementValue -- adds cash
		end
	end))


end)




game.Players.PlayerRemoving:Connect(function(Player) -- save function here

	--[{ DATA STORE SAVING }]--

	DataStore:SetAsync(Player.UserId, { -- gets data
		Level = Player.leaderstats.Level.Value,
	})

end)

Are you sure you are watching the correct video? The video I am referring to provides a full walkthrough to setup and use the module.

Video (The section after 17:03 is what you will be using but I recommend watching the whole video to grasp the system fully):

Does anything need to be edited from the original script?

Sorry just abit confused, Is it a completely new datastore system or does it just build on Roblox’s one

Got it working, Thank you for the suggestion

The way you will write it is pretty different, but at the core it still uses roblox’s datastore system. The module is basically a wrapper that improves upon the functionality of the default roblox datastore system. Also if you are interested in learning WHY exactly using a datastore wrapper is beneficial then I recommend this video:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.