Bug Description
When the game stream encounters a StopIteration (stream ends due to network blip, Lichess closing the connection, etc.), the bot unconditionally exits the game loop — even if the game is still in progress. This causes the bot to flag on time.
Root Cause
In lichess_bot.py lines 780-783:
except (HTTPError, ReadTimeout, RemoteDisconnected, ChunkedEncodingError, RequestsConnectionError,
StopIteration) as e:
stopped = isinstance(e, StopIteration)
stay_in_game = not stopped and (move_attempted or game_is_active(li, game.id))
Issue 1: When StopIteration fires, stay_in_game is set to False unconditionally (not stopped is False), bypassing both the move_attempted check and the game_is_active() check. A stream ending doesn't mean the game ended — it could be a transient network issue.
Issue 2: move_attempted is reset to False at the top of each loop iteration (line 726). So if the bot made a move on iteration N, and the exception fires on iteration N+1, move_attempted is already False. The fallback game_is_active() queries /api/account/playing, which can return stale data if called immediately after making a move (race condition).
Steps to Reproduce
- Bot is playing a game
- Bot makes a move successfully (HTTP 200 from
/api/bot/game/{id}/move/{move})
- Game stream connection drops (
StopIteration on next(lines))
- Bot exits game loop, kills engine
- Opponent makes a move, bot never responds
- Bot flags on time
Observed Behavior
From logs:
20:26:56 - Bot plays Qe2, move accepted (HTTP 200)
20:27:11 - Bot checks /api/account/playing, concludes game is over, quits engine
20:27:11 - "Game over" logged, engine process exits
20:32:08 - gameFinish event arrives with status "outoftime" — bot flagged
The bot quit the engine ~15 seconds after its last move, while the game was still ongoing.
Suggested Fix
On StopIteration, the bot should verify the game is still active via game_is_active() (with a small delay to avoid the race condition) before exiting, rather than unconditionally giving up:
except (HTTPError, ReadTimeout, RemoteDisconnected, ChunkedEncodingError, RequestsConnectionError,
StopIteration) as e:
stopped = isinstance(e, StopIteration)
if stopped:
time.sleep(1)
stay_in_game = move_attempted or game_is_active(li, game.id)
Environment
- lichess-bot version: 2026.2.13.1 (commit 960bcad)
- Running in Docker on Linux
Bug Description
When the game stream encounters a
StopIteration(stream ends due to network blip, Lichess closing the connection, etc.), the bot unconditionally exits the game loop — even if the game is still in progress. This causes the bot to flag on time.Root Cause
In
lichess_bot.pylines 780-783:Issue 1: When
StopIterationfires,stay_in_gameis set toFalseunconditionally (not stoppedisFalse), bypassing both themove_attemptedcheck and thegame_is_active()check. A stream ending doesn't mean the game ended — it could be a transient network issue.Issue 2:
move_attemptedis reset toFalseat the top of each loop iteration (line 726). So if the bot made a move on iteration N, and the exception fires on iteration N+1,move_attemptedis alreadyFalse. The fallbackgame_is_active()queries/api/account/playing, which can return stale data if called immediately after making a move (race condition).Steps to Reproduce
/api/bot/game/{id}/move/{move})StopIterationonnext(lines))Observed Behavior
From logs:
The bot quit the engine ~15 seconds after its last move, while the game was still ongoing.
Suggested Fix
On
StopIteration, the bot should verify the game is still active viagame_is_active()(with a small delay to avoid the race condition) before exiting, rather than unconditionally giving up:Environment