Repository: AUTOMATIC1111/stable-diffusion-webui

Issue:
[Bug]: /sdapi/v1/txt2img endpoint not working
### Is there an existing issue for this?

- [X] I have searched the existing issues and checked the recent builds/commits

### What happened?

Today when i tried to use my discord bot to make some requests to the endpoint /sdapi/v1/txt2img, i kept getting the error: "There is no current event loop in thread 'AnyIO worker thread'." Last successful generations were around 48h ago.

### Steps to reproduce the problem

1. Start fast-stable-diffusion colab version by TheLastBen [colab](https://colab.research.google.com/github/TheLastBen/fast-stable-diffusion/blob/main/fast_stable_diffusion_AUTOMATIC1111.ipynb)
2. . Make a post request using to the endpoint /sdapi/v1/txt2img (or using any other tool like Postman)
<img width="883" alt="1234" src="https://user-images.githubusercontent.com/5587806/227983838-6ba7cbb5-c416-4120-bafe-0273e065a5a7.png">
<img width="861" alt="12345" src="https://user-images.githubusercontent.com/5587806/227985350-b6d3f781-f28f-451b-9c95-748ddb574100.png">


### What should have happened?

Generate image and return success response json body with image path

### Commit where the problem happens

https://github.com/AUTOMATIC1111/stable-diffusion-webui/commit/955df7751eef11bb7697e2d77f6b8a6226b21e13

### What platforms do you use to access the UI ?

Other/Cloud

### What browsers do you use to access the UI ?

Google Chrome

### Command Line Arguments

```Shell
no
```


### List of extensions

no

### Console logs

```Shell
API error: POST: https://41209b1e8d4c8c9c05.gradio.live/sdapi/v1/txt2img {'error': 'RuntimeError', 'detail': '', 'body': '', 'errors': "There is no current event loop in thread 'AnyIO worker thread'."}
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py:94 in receive │
│                                                                              │
│ /usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py:89 in         │
│ receive_nowait                                                               │
╰──────────────────────────────────────────────────────────────────────────────╯
WouldBlock

During handling of the above exception, another exception occurred:

╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py:43 in    │
│ call_next                                                                    │
│                                                                              │
│ /usr/local/lib/python3.9/dist-packages/anyio/streams/memory.py:114 in        │
│ receive                                                                      │
╰──────────────────────────────────────────────────────────────────────────────╯
EndOfStream

During handling of the above exception, another exception occurred:

╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /content/gdrive/MyDrive/sd/stable-diffusion-webui/modules/api/api.py:145 in  │
│ exception_handling                                                           │
│                                                                              │
│   144 │   │   try:                                                           │
│ ❱ 145 │   │   │   return await call_next(request)                            │
│   146 │   │   except Exception as e:                                         │
│                                                                              │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │        call_next = <function                                             │ │
│ │                    BaseHTTPMiddleware.__call__.<locals>.call_next at     │ │
│ │                    0x7f45ac0faf70>                                       │ │
│ │                e = RuntimeError("There is no current event loop in       │ │
│ │                    thread 'AnyIO worker thread'.")                       │ │
│ │ handle_exception = <function api_middleware.<locals>.handle_exception at │ │
│ │                    0x7f45ac638dc0>                                       │ │
│ │          request = <starlette.requests.Request object at 0x7f45ac0b2790> │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│                                                                              │
│ /usr/local/lib/python3.9/dist-packages/starlette/middleware/base.py:46 in    │
│ call_next                                                                    │
│                                                                              │
│                           ... 25 frames hidden ...                           │
│                                                                              │
│ /usr/lib/python3.9/asyncio/locks.py:81 in __init__                           │
│                                                                              │
│    80 │   │   if loop is None:                                               │
│ ❱  81 │   │   │   self._loop = events.get_event_loop()                       │
│    82 │   │   else:                                                          │
│                                                                              │
│ ╭──────────────────────────── locals ─────────────────────────────╮          │
│ │ loop = None                                                     │          │
│ │ self = <asyncio.locks.Lock object at 0x7f45ac06b0a0 [unlocked]> │          │
│ ╰─────────────────────────────────────────────────────────────────╯          │
│                                                                              │
│ /usr/lib/python3.9/asyncio/events.py:642 in get_event_loop                   │
│                                                                              │
│   641 │   │   if self._local._loop is None:                                  │
│ ❱ 642 │   │   │   raise RuntimeError('There is no current event loop in thre │
│   643 │   │   │   │   │   │   │      % threading.current_thread().name)      │
│                                                                              │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ self = <asyncio.unix_events._UnixDefaultEventLoopPolicy object at        │ │
│ │        0x7f45adf50820>                                                   │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────╯
RuntimeError: There is no current event loop in thread 'AnyIO worker thread'.
```


### Additional information

_No response_


Discussion:
same here, must be a new thing
Can confirm, just updated my webui installation and it broke the API
I guess I have to downgrade then...
Same
same
I also encountered the same problem.
Same error on Colab.
On local Windows PC - OK (just done fresh install).
yep. same issue in colab

If this problem is on colab, it's a Linux problem I believe since I try to make the API work on my server.
Isn't there any solution?
Could anyone solve this?
any solution for colab?
i didnt find anything yet
sry wrong button
Same here. I'm using 'git checkout 9377092a892687a8ae43ba5f7df44f0929ab2997' as a temporary solution
I have the same problem
Another workaround while keeping the latest commit is to edit the `modules/api/api.py`.
I don't think this is a good solution though, so I don't want to make a PR.

```diff
diff --git a/modules/api/api.py b/modules/api/api.py
index 518b2a61..a9cef928 100644
--- a/modules/api/api.py
+++ b/modules/api/api.py
@@ -29,6 +29,7 @@ from modules import devices
 from typing import List
 import piexif
 import piexif.helper
+import asyncio
 
 def upscaler_to_index(name: str):
     try:
@@ -276,6 +277,15 @@ class Api:
         return script_args
 
     def text2imgapi(self, txt2imgreq: StableDiffusionTxt2ImgProcessingAPI):
+        try:
+            loop = asyncio.get_event_loop()
+        except RuntimeError as e:
+            if str(e).startswith('There is no current event loop in thread'):
+                loop = asyncio.new_event_loop()
+                asyncio.set_event_loop(loop)
+            else:
+                raise
+
         script_runner = scripts.scripts_txt2img
         if not script_runner.scripts:
             script_runner.initialize_scripts(False)
```
same
@MeemeeLab solution worked... thanks for this.
until some1 fix this issue, @MeemeeLab solution is working fine, thanks for the help.
The issue is in the source code.

```
def get_event_loop(self):
    """Get the event loop.
    This may be None or an instance of EventLoop.
    """
    if (self._local._loop is None and
            not self._local._set_called and
            isinstance(threading.current_thread(), threading._MainThread)):
        self.set_event_loop(self.new_event_loop())

    if self._local._loop is None:
        raise RuntimeError('There is no current event loop in thread %r.'
                            % threading.current_thread().name)

    return self._local._loop
```
> The issue is in the source code.
> 
> ```
> def get_event_loop(self):
>     """Get the event loop.
>     This may be None or an instance of EventLoop.
>     """
>     if (self._local._loop is None and
>             not self._local._set_called and
>             isinstance(threading.current_thread(), threading._MainThread)):
>         self.set_event_loop(self.new_event_loop())
> 
>     if self._local._loop is None:
>         raise RuntimeError('There is no current event loop in thread %r.'
>                             % threading.current_thread().name)
> 
>     return self._local._loop
> ```

I belive it's internal code of asyncio, there's should be a mistake in the code, not in the library.

Resolving patch:
diff --git a/webui.py b/webui.py
--- a/webui.py
+++ b/webui.py
@@ -5,6 +5,7 @@
 import signal
 import re
 import warnings
+import asyncio
 from fastapi import FastAPI
 from fastapi.middleware.cors import CORSMiddleware
 from fastapi.middleware.gzip import GZipMiddleware
@@ -66,6 +67,46 @@
 else:
     server_name = "0.0.0.0" if cmd_opts.listen else None
 
+if sys.platform == "win32" and hasattr(asyncio, "WindowsSelectorEventLoopPolicy"):
+    # "Any thread" and "selector" should be orthogonal, but there's not a clean
+    # interface for composing policies so pick the right base.
+    _BasePolicy = asyncio.WindowsSelectorEventLoopPolicy  # type: ignore
+else:
+    _BasePolicy = asyncio.DefaultEventLoopPolicy
+
+
+class AnyThreadEventLoopPolicy(_BasePolicy):  # type: ignore
+    """Event loop policy that allows loop creation on any thread.
+
+    The default `asyncio` event loop policy only automatically creates
+    event loops in the main threads. Other threads must create event
+    loops explicitly or `asyncio.get_event_loop` (and therefore
+    `.IOLoop.current`) will fail. Installing this policy allows event
+    loops to be created automatically on any thread, matching the
+    behavior of Tornado versions prior to 5.0 (or 5.0 on Python 2).
+
+    Usage::
+
+        asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy())
+
+    .. versionadded:: 5.0
+
+    """
+
+    def get_event_loop(self) -> asyncio.AbstractEventLoop:
+        try:
+            return super().get_event_loop()
+        except (RuntimeError, AssertionError):
+            # This was an AssertionError in python 3.4.2 (which ships with debian jessie)
+            # and changed to a RuntimeError in 3.4.3.
+            # "There is no current event loop in thread %r"
+            loop = self.new_event_loop()
+            self.set_event_loop(loop)
+            return loop
+
+
+asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy())
+
 
 def check_versions():
     if shared.cmd_opts.skip_version_check:


Test patch: