actually it's pretty simple once you see it:
There are some operations that must not be performed in every game tick (not needed for the functionality and has potentially massive performance impact). The "standard" approach is to distribute the updates over multiple ticks, such that each tick only updates some entities. My work queue was divided into 120 groups. The simplest way to distribute the locomotives into these groups is to simply divide the ID by 120 and then take the remainder as the group number: A locomotive with ID 240 would be in group 0, one with ID 256 would be in group 16, etc...
Here the problem was that usually arrays are zero-indexed (i.e. the groups would be numbered 0-119). But LUA arrays are one-indexed, so the group numbers need be 1-120. While my broken calculation usually worked, whenever a locomotive ID was divisible by 120, the calculated group ID would be 0. But 0 is no valid index, and it crashes.
In essence it is a simple off-by-one-error. Trivial to fix, but a pain to spot.