Message 208956 - Python tracker
There is a subtlety in the as_completed() code which explains a lot - note that "finished" starts off as a set in the _AcquireFutures block. So if a Future f has already completed, as_completed( [f,f] ) will only yield f once, because f appears once in the finished set. Later on when waiter events are processed, "finished" turns into a list because of the line: finished = waiter.finished_futures So any duplicates in that list will cause problems in pending.remove(Future).