Invalid argument #2 to 'random' (interval is empty)

hello i am working on a game and came across this error but i have no idea how to fix it
if anybody is nice enough to help me out here
the error is happening inside of a module script

local ItemProperties = require(game.ServerScriptService.ItemProperties)
local Items = game.ServerStorage.Items

local ItemDistribution = {}

function ItemDistribution.SpawnItem(spawner)
	local ItemTable = ItemProperties[spawner.Name]
	if math.random(1, 3) > 1 then
		for val = 1, math.random(2, 3) do
			local RandomItem = Items:FindFirstChild(ItemTable[math.random(1, #ItemTable)]):Clone() -- this is where the error is happening
			RandomItem.Parent = workspace.Items
			if RandomItem:IsA("Model") then
				RandomItem:MoveTo(spawner.Position+Vector3.new(math.random(-5, 5), -3, math.random(-5, 5)))
			elseif RandomItem:IsA("BasePart") then
				RandomItem.Position = spawner.Position+Vector3.new(math.random(-5, 5), -3, math.random(-5, 5))
			end
		end
	end
end

return ItemDistribution
2 Likes

This might be because #ItemTable is 0
to confirm, print it, and if it is, then only run the function if #ItemTable is over 0

1 Like

just checked if it prints 0 and it does

and how can i fix it the error?

Work backwards; find out why your table is empty

i also have tried printing the ItemTable and it prints all the stuff inside of the table

the table isint empty i have tested print(ItemTable) and it does print every single thing inside of the table but if i do print(#ItemTable) it prints out 0

Thats probably because you have non-number indexes/keys and # only works on arrays
to fix this, insert this after the local ItemTable line

local len = 0
for i,_ in ItemTable do
    len += 1
end

this gives us the actual length of the table, even if it has non-number indexes/keys!
Now you can replace #ItemTable with len in the script

1 Like

I see the problem here. Tables are divided into two categories: dictionaries and arrays. The length operator only reports the length of the table’s array component–dictionary length is always 0. Arrays are characterized by ascending numerical indices starting from 1, which is why we can pull random elements from the array through generating a random index between 1-#array. A dictionary’s key-value pairs are not characterized by this, meaning the same math.random approach will not work.

To get a random key-value pair from a dictionary, you need to collect its keys into an array and chose one by random. Do this, or try to convert your dictionary into an array

now it throws another error Argument 1 missing or nil

Put this after the loop I sent earlier

local Iteration,RandomIter,RandomValue = 0, math.random(1,len), nil
for i,v in ItemTable do
    i += 1
    if i == RandomIter then
        RandomValue = v
        break
    end
end

and replace ItemTable[math.random(1, len)] (in FindFirstChild) with RandomValue

its sending a error at i += 1 attempt to perform arithmetic (add) on string and number

oops, i meant to write Iteration instead of i in that line and the line after

the rest works but now its sending an error at local RandomItem = Items:FindFirstChild(RandomValue):Clone() Argument 1 missing or nil

local function randomKeyValue<K, V>(dictionary: {[K]: V}): (K, V)
	local length = 0

	for _ in dictionary do
		length += 1
	end

	local index = 0
	local randomIndex = math.random(length)

	for key, value in dictionary do
		index += 1

		if index == randomIndex then
			return key, value
		end
	end
	
	-- Silence NACP
	return nil :: any, nil :: any 
end

where should i add it? like this local RandomItem = Items:FindFirstChild(math.random(1, randomKeyValue(ItemProperties))):Clone()

local _, randomItem = randomKeyValue(ItemTable)

should it look like this? local RandomItem = Items:FindFirstChild(randomItem):Clone()

What if you put it above the local RandomItem line? (The whole local Iteration… for i,v… i mean)

1 Like

That depends on what your key-value pair is. Is the item name the key, or the value associated with the key?