{"record":{"id":"5e3bb8d6ac7c7146","repo":"SeleniumHQ/selenium","slug":"the-command-s-generator-function-did-not-exit-when","errorCode":null,"errorMessage":"The command's generator function did not exit when expected!","messagePattern":"The command's generator function did not exit when expected!","errorType":"exception","errorClass":"WebDriverException","httpStatus":null,"severity":"error","filePath":"py/selenium/webdriver/remote/websocket_connection.py","lineNumber":174,"sourceCode":"        return id(_callback)\n\n    on = add_callback\n\n    def remove_callback(self, event, callback_id):\n        event_name = event.event_class\n        if event_name in self.callbacks:\n            for callback in self.callbacks[event_name]:\n                if id(callback) == callback_id:\n                    self.callbacks[event_name].remove(callback)\n                    return\n\n    def _serialize_command(self, command):\n        return next(command)\n\n    def _deserialize_result(self, result, command):\n        try:\n            _ = command.send(result)\n            raise WebDriverException(\"The command's generator function did not exit when expected!\")\n        except StopIteration as exit:\n            return exit.value\n\n    def _start_ws(self):\n        def on_open(ws):\n            self._started = True\n\n        def on_message(ws, message):\n            self._process_message(message)\n\n        def on_error(ws, error):\n            logger.debug(f\"error: {error}\")\n            ws.close()\n\n        def run_socket():\n            if self.url.startswith(\"wss://\"):\n                self._ws.run_forever(sslopt={\"cert_reqs\": CERT_NONE}, suppress_origin=True)\n            else:","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/selenium/webdriver/remote/websocket_connection.py#L156-L192","documentation":"Internal assertion in _deserialize_result. BiDi command objects are generator-based: _serialize_command does next(command) for the request, and _deserialize_result does command.send(result) expecting the generator to terminate (StopIteration) and return its parsed value. If the generator yields again instead of returning, this error fires - meaning the command implementation is structurally wrong.","triggerScenarios":"A BiDi command class whose generator has more than one yield, or a custom/monkeypatched command that does not `return` after consuming the result. Not triggered by ordinary inputs.","commonSituations":"Almost exclusively a Selenium-internal defect, or a user who subclassed/extended the BiDi command generators incorrectly.","solutions":["Report upstream - this indicates a defect in the command implementation, not your inputs.","If you wrote a custom command, ensure its generator yields exactly once then returns the parsed result.","Pin/upgrade the selenium version where the command works correctly."],"exampleFix":"# custom command generator - before (yields twice)\n# def cmd():\n#     payload = yield {...}\n#     extra = yield {...}   # wrong\n#     return parse(payload)\n\n# after (yield once, then return)\ndef cmd():\n    payload = yield {\"method\": \"x\", \"params\": {}}\n    return parse(payload)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = conn.execute(cmd)\nexcept WebDriverException as e:\n    if \"generator function did not exit\" in str(e):\n        log.error(\"Defective BiDi command implementation: %r\", cmd)\n        raise","preventionTips":["Do not hand-author BiDi command generators unless following the single-yield contract.","Pin a known-good selenium release when relying on BiDi commands."],"tags":["bidi","internal","bug","generator"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}