Lua table gotcha

I recently was introduced to a bug in my game. I had 20 AI units and only 19 of them were actively doing something. Number 20 was just standing there. The problem eventually lied in using '#enemies' to get the amount of enemies.

Here is what happened:

A lua table index by default starts on index 1. This in contrary to many other languages where it starts at 0. However, you can assign a value to index '0' if you want. Since I use C# on a daily basis, I am more comfortable using the 0 index as a start. As a result this is my (simplified) code:

for i = 0, enemyCount-1, do
enemies[i] = new Enemy()                          
end

In the AI script I loop over the enemies like this:

for i = 0, #enemies-1, do
enemies[i]:DoStuff()                          
end

This is really basic lua scripting with one tiny gotcha: The '#' is used to get the amount of consecutive keyed items in the list. This I knew. What I did not know, is that there is also the requirement that this order starts at index 1 (or at least not on index 0). It simply ignores the 0 index!

Here is a full script to try

local enemies = {}
local enemyCount = 4
for i = 0, enemyCount-1, 1 do
enemies[i] = "I am enemy " .. i
System:Print(enemies[i])                  
end

System:Print("#enemiesCount: " .. #enemies) 

for i = 0, #enemies-1 do
System:Print(enemies[i])                  
end 

Output:

I am enemy 0
I am enemy 1
I am enemy 2
I am enemy 3

#enemiesCount: 3

I am enemy 0
I am enemy 1
I am enemy 2

Problem
So what was happening? I did get the amount of enemies back, except for the one enemy that was located on index 0. I quickly noticed the lower count of enemies, but since enemy number 20 wasn't doing anything I was also looking in the wrong place. It was actually enemy number 1 that was the culprit, even though it's AI was being executed.

Solution
It can be solved in numerous simple ways, but I guess best practice is to just stick to Lua's standard and not assign anything to 0. This can really prevent some time being wasted on absolutely silly issues like this.