python-chess icon indicating copy to clipboard operation
python-chess copied to clipboard

assert while using an UCI program

Open folkertvanheusden opened this issue 3 months ago • 4 comments

Hi,

I often get this error when talking to a UCI program using python-chess:

Exception in callback Protocol._line_received()
handle: <Handle Protocol._line_received()>
Traceback (most recent call last):
  File "/usr/lib/python3.13/asyncio/events.py", line 89, in _run
    self._context.run(self._callback, *self._args)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/folkert/.local/lib/python3.13/site-packages/chess/engine.py", line 1040, in _line_received
    self.command._line_received(self, line)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/home/folkert/.local/lib/python3.13/site-packages/chess/engine.py", line 1289, in _line_received
    assert self.state in [CommandState.ACTIVE, CommandState.CANCELLING]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError

What is causing it? Can I prevent it somehow?

Thanks!

folkertvanheusden avatar Sep 07 '25 15:09 folkertvanheusden

Hi. Please include some more details:

  • Debug logs (https://python-chess.readthedocs.io/en/latest/engine.html#logging).
  • Which engine (and version) are you using?
  • Are you using chess.engine via asyncio or SimpleEngine?

niklasf avatar Sep 07 '25 15:09 niklasf

Hi,

The debug logs are attached now. I'm using stockfish 16 from ubuntu and my own program (called Dog). Dog uses https://github.com/Mk-Chan/libchess to do the UCI protocol. I talk to them via chess.engine.SimpleEngine.

log.zip

The code is (abbreviated):

def score_for_pos(prog, fen, color):
    board = chess.Board(fen)
    info = prog.analyse(board, chess.engine.Limit(time=analysis_time))
    return info['score'].pov(color).score()
...
            engineA = chess.engine.SimpleEngine.popen_uci(aproc)
            engine1 = chess.engine.SimpleEngine.popen_uci(proc)
            engine2 = chess.engine.SimpleEngine.popen_uci(proc)
...
            white_prev_score = score_for_pos(engineA, b.fen(), chess.WHITE)
...
                    result = engine1.play(b, chess.engine.Limit(time=time_), info=chess.engine.INFO_BASIC | chess.engine.INFO_SCORE)

and so on.

folkertvanheusden avatar Sep 07 '25 15:09 folkertvanheusden

Thanks. Looks like it's due to the output

Thread 0 started

from Dog (in a phase where no output is expected). It's not UCI, but arguably should just be a warning.

niklasf avatar Sep 07 '25 16:09 niklasf

Thanks. Looks like it's due to the output

Thread 0 started

from Dog (in a phase where no output is expected). It's not UCI, but arguably should just be a warning.

Is this something you're going to work around indeed?

folkertvanheusden avatar Sep 07 '25 20:09 folkertvanheusden