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

  1. Ensure the future is actually awaited/completed before any code calls quit_event_loop() or stops the loop.
  2. Don't call run_until_complete with futures whose completion depends on UI events that may never fire (window closed, etc.).
  3. 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

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


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)