invalid key to 'next' in function '(for generator)'

What would cause this error?

[lua]

2013-08-12 07:47:25.102 Corona Simulator[1909:1c03] Runtime error

invalid key to ‘next’

stack traceback:

    [C]: ?

    [C]: in function ‘(for generator)’

    …

[/lua]

I’m iterating through a perfectly valid table, using pairs(). Every now and then, apparently for no reason, it’ll throw that error.

Is there some event triggering that might be deleting entries from your table as your looping through it?

Am I not supposed to remove things from a table when iterating through it? I am removing things from it - could that be the problem?

  • C

You can remove them while iterating through. What I was asking is do you have something else like a collision detection event, a runtime listener or something that could be removing items for you while you are trying to remove them.

I’m using my own timer solution library, so it’s iterating through my list of timers. I’m also stopping a timer sometimes when it’s iterated. I checked into my program, and here’s the result:

[lua]

  • Eternal timer running to fire shots from a turret

  - Within the fire function, it first checks a flag to see whether it should stop on this shot

    - If flag is true, stops the timer and resets the flag

      -> Error is thrown

    - Otherwise proceeds

  - Otherwise it fires

  • End of fire function

[/lua]

So if removing the index (stopping the timer) within the iteration isn’t something you’re supposed to do, how would I achieve this?

  • C

Be good to see some code - the only thing I can guess at this stage is whether you’re facing the “iterate-backwards” approach required when deleting entries from a table.

http://stackoverflow.com/questions/12394841/safely-remove-items-from-an-array-table-while-iterating

I’m using pairs()…

Here’s some code:

Relavent timer code:

[lua]


– The iteration function


    for k, v in pairs(timerStack) do

        if timerStack[k] and timerStack[k].running then – Not paused

            --print("iterating "…k)

            if time>=(timerStack[k].time * timerStack[k].iterCount)+timerStack[k].timeOffset then

                timerStack[k].iterCount=timerStack[k].iterCount+1 – Number of iterations

                if timerStack[k].iterations>1 then

                    timerStack[k].iterations=timerStack[k].iterations-1

                    timerStack[k].func()

                elseif timerStack[k].iterations==1 then – Finished iterations

                    timerStack[k].func()

                    timerStack[k].onComplete()

                    timerStack[k] = nil

                end


– The stop function


– After various nil checks…

timerStack[handle._timerStack_key] = nil – Delete a timer

handle = nil

[/lua]

And here’s the relavent turret code:

[lua]

if turret.stopAfterNextFire then – Stop for updates so we can reset the turret’s fire speed

                spark.stop(turret.fireTimer)

                turret.fireTimer = spark.timer(turret.speed, turret.fire, 0)  – turret.fire is the function that this code is found inside

                turret.stopAfterNextFire = false

            end

[/lua]

Any ideas?

  • C

I’m being stupid - you mentioned pairs() you’ve obviously got an indexed array, so iterating backwards was never going to be relevant. 

When you mentioned next in the original post, I presume that’s where you’re now using k,v in pairs() ???

Yep - I guess pairs() uses next() to do it’s iterating.

  • C

Is your timerStack indexed by number or by key?

By key.

Actually, what I’m doing is creating random unique alphanumeric keys and pairs()-ing through them, because I’m not really sure how to use indexing. :slight_smile:

  • C

I think most people would use an integer index and use traditional for i = 1, tablesize do / end type constructs to manage those types of loops.  Key-value pairs are good when you have a natural index that’s not a number, but it sounds like for what your doing the index doesn’t matter.

You can add things to the end of a table pretty easy using the # operator (gets table length):

mytable[#mytable+1] = value

Then to remove an entry, you can use table.remove… for instance to remove the 3rd entry:  table.remove(mytable, 3).

And to iterate over the table (best for removing things is to go backwards):

for i = #mytable, 1 do

    – do whatever

end

And indexing like that won’t have any *issues* (caused by the indexing, not the coder)?

  • C

The only thing is deleting things from the middle of the list and using the # operator to measure the length of the array.  If you have an array:

x[1] = 10

x[2] = 15

x[3] = nil

x[4] = “Barney”

x[5] = “Wilma”

Then #x returns 2.  The nil stops the counting.  There are two solutions.  One is to use table.maxn(x) to get the actual count of records and when iterating over it, skip the nil’s or two: table.remove(x, 3) to remove the entry.  The later will copy  4 to 3, 5 to 4 to collapse out the hole, so it can be a bit time consuming if you have 100,000 times and you remove #4 for instance.  

Of course if you use table.maxn() and you iterate over a list of 100,000 that 90% of them have been removed, that can be inefficient too.   So a combination of the two, use maxn() and then periodically purge the nil’s and get a new maxn()

Is there some event triggering that might be deleting entries from your table as your looping through it?

Am I not supposed to remove things from a table when iterating through it? I am removing things from it - could that be the problem?

  • C

You can remove them while iterating through. What I was asking is do you have something else like a collision detection event, a runtime listener or something that could be removing items for you while you are trying to remove them.

I’m using my own timer solution library, so it’s iterating through my list of timers. I’m also stopping a timer sometimes when it’s iterated. I checked into my program, and here’s the result:

[lua]

  • Eternal timer running to fire shots from a turret

  - Within the fire function, it first checks a flag to see whether it should stop on this shot

    - If flag is true, stops the timer and resets the flag

      -> Error is thrown

    - Otherwise proceeds

  - Otherwise it fires

  • End of fire function

[/lua]

So if removing the index (stopping the timer) within the iteration isn’t something you’re supposed to do, how would I achieve this?

  • C

Be good to see some code - the only thing I can guess at this stage is whether you’re facing the “iterate-backwards” approach required when deleting entries from a table.

http://stackoverflow.com/questions/12394841/safely-remove-items-from-an-array-table-while-iterating

I’m using pairs()…

Here’s some code:

Relavent timer code:

[lua]


– The iteration function


    for k, v in pairs(timerStack) do

        if timerStack[k] and timerStack[k].running then – Not paused

            --print("iterating "…k)

            if time>=(timerStack[k].time * timerStack[k].iterCount)+timerStack[k].timeOffset then

                timerStack[k].iterCount=timerStack[k].iterCount+1 – Number of iterations

                if timerStack[k].iterations>1 then

                    timerStack[k].iterations=timerStack[k].iterations-1

                    timerStack[k].func()

                elseif timerStack[k].iterations==1 then – Finished iterations

                    timerStack[k].func()

                    timerStack[k].onComplete()

                    timerStack[k] = nil

                end


– The stop function


– After various nil checks…

timerStack[handle._timerStack_key] = nil – Delete a timer

handle = nil

[/lua]

And here’s the relavent turret code:

[lua]

if turret.stopAfterNextFire then – Stop for updates so we can reset the turret’s fire speed

                spark.stop(turret.fireTimer)

                turret.fireTimer = spark.timer(turret.speed, turret.fire, 0)  – turret.fire is the function that this code is found inside

                turret.stopAfterNextFire = false

            end

[/lua]

Any ideas?

  • C