slint-ui/slint · error · RuntimeError
run_until_complete's future isn't done
Error message
run_until_complete's future isn't done
What it means
Raised by run_until_complete when the event loop stopped before the awaited future completed AND the stop was not initiated by the loop's own quit mechanism (stop_run_forever_event set). The result value is therefore unavailable.
Solutions
- Ensure the future is actually awaited/completed before any code calls quit_event_loop() or stops the loop.
- Don't call run_until_complete with futures whose completion depends on UI events that may never fire (window closed, etc.).
- Wrap in try/except RuntimeError and handle the not-done case (e.g. cancel the future or treat the result as None).
Example fix
// before
result = slint.loop.run_until_complete(some_coro) # may raise if loop stopped
# after
try:
result = slint.loop.run_until_complete(some_coro)
except RuntimeError:
some_task.cancel()
result = None Defensive patterns
Strategy: try-catch
Type guard
def future_done(f):
return f.done() Try / catch
try:
result = loop.run_until_complete(fut)
except RuntimeError as e:
if "isn't done" in str(e):
fut.cancel()
result = None
else:
raise Prevention
- Never call quit_event_loop() while awaited futures are pending.
- Drive long-running async work with ensure_future + the Slint loop's quit callback instead of run_until_complete.
When it happens
Trigger: Calling loop.run_until_complete(future) while another thread or code path stops the loop (e.g. slint.quit_event_loop()) before the future resolves; nesting run_until_complete calls; an exception path that terminates the loop early.
Common situations: Quitting the app from a UI callback while an async task awaited via run_until_complete is still pending; running the Slint loop and an asyncio future concurrently and stopping the loop from a window-close handler.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Callback ' ' cannot be used with a callback decorator for…
- Callback ' ' cannot be used with a callback decorator for…
- Callback ' ' in global ' ' cannot be used with a callback…
- Callback ' ' in global ' ' cannot be used with a callback…
- Could not compile
AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16).
Data as JSON: /api/errors/97692004fc96b4df.
Report an issue: GitHub.
Appendix: source
Thrown at api/python/slint/slint/loop.py:187
asyncio.events._set_running_loop(None)
def run_until_complete[T](self, future: typing.Awaitable[T]) -> T | None:
def stop_loop(future: typing.Any) -> None:
self.stop()
future = asyncio.ensure_future(future, loop=self)
future.add_done_callback(stop_loop)
try:
self.run_forever()
finally:
future.remove_done_callback(stop_loop)
if future.done():
return future.result()
else:
if self.stop_run_forever_event.is_set():
raise RuntimeError("run_until_complete's future isn't done", future)
else:
# If the loop was quit for example because the user closed the last window, then
# don't thrown an error but return a None sentinel. The return value of asyncio.run()
# isn't used by slint.run_event_loop() anyway
# TODO: see if we can properly cancel the future by calling cancel() and throwing
# the task cancellation exception.
return None
def _run_forever_setup(self) -> None:
pass
def _run_forever_cleanup(self) -> None:
pass
def stop(self) -> None:
self.stop_run_forever_event.set()
def is_running(self) -> bool:View on GitHub (pinned to bb937076de)