Basically, when using async iterators (AsyncIter, AsyncResultIter), please stay away from toSeq(iter) where iter is an instance of unfinished async iterator.

It will basically end-up in an endless loop and will eat all your computers memory…

This is because toSeq under the hood will just use items but without awaiting on the returned future. Here is how items is defined:

iterator items*[T](self: AsyncResultIter[T]): auto {.inline.} =
  while not self.finished:
    yield self.next()

There is no way in current Nim to create a truly async iterator. In the code above, the while loop will not finish till self.finished evaluates to true. But this can never happen if the caller of the items iterator never awaits on the returned value (which will be a Future in the case of any of our async iterators). Only when awaiting, next will update the iterator state and potentially set finished member to true:

proc next(): Future[?!T] {.async: (raises: [CancelledError]).} =
	try:
	  if not iter.finished:
		let item = await genNext()
		if finishOnErr and err =? item.errorOption:
		  iter.finished = true
		  return failure(err)
		if isFinished():
		  iter.finished = true
		return item
	  else:
		return failure("AsyncResultIter is finished but next item was requested")
	except CancelledError as err:
	  iter.finished = true
	  raise err