I've solved this but it took me several hours to find the problem, so I'm posting here as a reference.
The TTS API documentation says of object.removeButton(n), "Removing an index instantly causes all other higher indexes to shift down 1." That's not quite true. Apparently that shift is done on the next frame. In order to delete all buttons, you need something like
Code:
for i=0, buttonCount-1 do
self.targetObject.removeButton(i) -- delete from first to last
end
or
Code:
for i = buttonCount-1, 0, -1 do
self.targetObject.removeButton(i) -- delete from last to first element
end
and not
Code:
for i=0, buttonCount-1 do
self.targetObject.removeButton(0) -- delete first element n times
end
If the array elements were immediately shifted to fill the removed slot, as they would be with an ordinary Lua array, the latter would work -- deleting the first element n times since the others will be shifted down to fill it. But this does not work.