I have the following loop:
while true:
    var
      timeout = false
      readKeys = false
    block:
      var
        keyFuture: Future[string]
        timeoutFuture: Future[void]
        sequence: string
      keyFuture = this.terminal.key()
      if keyTranslator.activeSequence.len > 0:
        debugEcho "active sequence: ", keyTranslator.activeSequence, ", timeout"
        timeoutFuture = sleepAsync(300)  # TODO: make constant
        timeout = true
        timeoutFuture.callback =
          proc () =
            if not keyFuture.finished:
              keyFuture.complete("")
      debugEcho "wait…"
      yield keyFuture
      debugEcho "…done"
      sequence = keyFuture.read
      asyncCheck keyFuture
      if timeout:
        timeoutFuture.clearCallbacks
      debugEcho "read sequence: ", sequence.escape
      readKeys = keyTranslator.keySequence(sequence)
    debugEcho "end block"
    debugEcho "readKeys=", readKeys
    if readKeys:
      for k in keyTranslator.read:
        debugEcho "read key: ", k.toUTF8.escape, " (", k.int.toHex, ")"
        if k == F1.Rune: # XXX for testing only
          debugEcho "F1!"
          this.isRunning = false
          return
        if this.screen.focus != -1:
          this.send KeyEvent(this.time, this.screen.focus, k)
    debugEcho "end loop"
 This gets the following error on the yield statement after once the timeoutFuture was active and completed the keyFuture and then the keyFuture is used without the timeout:
Error: unhandled exception: An attempt was made to complete a Future more than once. Details:
  Future ID: 510
  Created in proc: asyncfile.read
  Stack trace to moment of creation:
    /home/j/Personal/Projects/nim/term/src/test2.nim(55)                     test2
      /home/j/Personal/Projects/nim/term/src/test2.nim(52)                     main
      /home/j/Personal/Projects/nim/term/src/term/engine.nim(211)              run
      /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncdispatch.nim(1576) poll
      /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncdispatch.nim(1340) runOnce
      /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncdispatch.nim(210)  processPendingCallbacks
      /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncmacro.nim(34)      keyboardInputNimAsyncContinue
      /home/j/Personal/Projects/nim/term/src/term/engine.nim(173)              keyboardInputIter
      /home/j/Personal/Projects/nim/term/src/term/term.nim(63)                 key
      /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncfile.nim(209)      read
      /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncfutures.nim(110)   newFuture
  Contents (string):
  
  Stack trace to moment of secondary completion:
    Traceback (most recent call last)
    /home/j/Personal/Projects/nim/term/src/test2.nim(55) test2
    /home/j/Personal/Projects/nim/term/src/test2.nim(52) main
    /home/j/Personal/Projects/nim/term/src/term/engine.nim(211) run
    /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncdispatch.nim(1576) poll
    /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncdispatch.nim(1306) runOnce
    /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncdispatch.nim(1214) processBasicCallbacks
    /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncfile.nim(290) cb
    /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncfutures.nim(211) complete
    /home/j/.choosenim/toolchains/nim-1.2.0/lib/pure/asyncfutures.nim(154) checkFinished [FutureError]
 I don't understand why the async system wants to complete the keyFuture when it was already completed. I put the keyFuture into a block that should remove the future all together. Could this be a bug in asyncdispatch/asyncfutures?