Hi guys i am getting error when events inside dynamic render are triggered and they have .then() to some function. I think is some problem of async sincronism, because some time works. I have debuged the code and i noticed that in queueing.py on push method:
when it try return the function from collection it not exists anymore. maybe because elements are removed from render before the function is called.
Have you searched existing issues? π
[X] I have searched and found no existing issues
Reproduction
Try add a controlnet, and then remove it on X button, do it more than twice util errors happen,
My remove_controlnet.click() is calling in then update_reference_elements() function where errors occours.
here is my app to test.
import time
import gradio as gr
selected_controlnets=[]
controlnet_scales=[]
CONTROLNETS = ["canny", "pose"]
def clean_status(current_status):
if current_status is not None and current_status != '':
time.sleep(5)
return None
def click_add_controlnet(controlnet):
if controlnet not in selected_controlnets:
selected_controlnets.append(controlnet)
return selected_controlnets, None
else:
return selected_controlnets, "This model has already been added!"
def submit_button(progress=gr.Progress(track_tqdm=True)):
print('Testing')
for i in controlnet_scales:
print(f"key: {i.key[8:]}, value:{i.value}")
return "See the result in the terminal!"
def update_reference_elements():
outputs=[*[gr.update(visible=False)] * 2]
for c in selected_controlnets:
if c == 'canny':
outputs[0]=gr.update(visible=True)
if c == 'pose':
outputs[1]=gr.update(visible=True)
return outputs
with gr.Blocks(analytics_enabled=False) as app:
with gr.Row():
with gr.Column(scale=0.4, min_width=100):
controlnet_models = gr.Dropdown(label="Control Type", choices=CONTROLNETS, value=CONTROLNETS[0])
with gr.Column(scale=0, min_width=50):
refresh_controlnet = gr.Button(value="Refresh", elem_id="controlnet_refresh_button")
with gr.Column(scale=0, min_width=50):
add_controlnet = gr.Button(value="+", elem_id="add_controlnet_button")
with gr.Column(scale=0, min_width=50):
submit_test = gr.Button(value="Submit", elem_id="submit_button" )
with gr.Row():
status = gr.Textbox(label="Status", value="", show_label=False)
with gr.Row():
with gr.Column():
selected_controlnet_state= gr.State(value=selected_controlnets)
@gr.render(inputs=selected_controlnet_state)
def render_loras(selected):
global controlnet_scales
with gr.Row(elem_id="control_row"):
for i in range(len(selected)):
control_name = selected[i]
with gr.Column(variant="panel", min_width=300):
with gr.Row():
with gr.Column(min_width=300):
remove_controlnet = gr.Button(value="X", key=f"remove-control-{control_name}", elem_classes="remove-button vertical-center")
controlnet = gr.Textbox(label="File name", value=f"{control_name}", key=f"label-{control_name}", show_label=True)
control_scale = gr.Slider(
interactive=True,
minimum=0.1,
maximum=2.0,
step=0.01,
value=0.1,
label="Control scale",
key=f"scale-{control_name}")
def click_remove_controlnet(value, canny_image, pose_image, controlnet=control_name):
for l in range(len(controlnet_scales)):
if controlnet in controlnet_scales[l].key:
controlnet_scales.pop(l)
break
selected_controlnets.pop(selected_controlnets.index(value))
canny_value=None if value == 'canny'else canny_image
pose_value=None if value == 'pose' else pose_image
return selected_controlnets, gr.update(value=canny_value), gr.update(value=pose_value), f"Control {value} removed!"
remove_controlnet.click(fn=click_remove_controlnet, inputs=[controlnet, canny_image, pose_image], outputs=[selected_controlnet_state, canny_image, pose_image, status]) \
.then(fn=update_reference_elements, outputs=[col_canny_image, col_pose_image]) \
.then(fn=clean_status, inputs=status)
def change_control_scale(value, controlnet=control_name):
for l in range(len(controlnet_scales)):
if controlnet in controlnet_scales[l].key:
controlnet_scales[l].value=value
control_scale.release(fn=change_control_scale, inputs=control_scale)
hasControlnet = False
for l in range(len(controlnet_scales)):
if control_name in controlnet_scales[l].key:
hasControlnet = True
break
if not hasControlnet:
controlnet_scales.append(control_scale)
with gr.Row():
with gr.Column(scale=0, min_width=300, visible=False) as col_canny_image:
with gr.Row():
canny_image = gr.Image(label="Image for canny", elem_classes="ipa", visible=True, streaming=False)
with gr.Column(scale=0, min_width=300, visible=False) as col_pose_image:
with gr.Row():
pose_image = gr.Image(label="Image for pose", elem_classes="ipa", visible=True, streaming=False)
add_controlnet.click(fn=click_add_controlnet, inputs=controlnet_models, outputs=[selected_controlnet_state, status]) \
.then(fn=update_reference_elements, outputs=[col_canny_image, col_pose_image]) \
submit_test.click(
fn=submit_button,
outputs=status)
app.launch(inbrowser=True)
``
Screenshot
N/A
Logs
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 398, in run_asgi
result = await app( # type: ignore[func-returns-value]
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 70, in __call__
return await self.app(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\fastapi\applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\applications.py", line 123, in __call__
await self.middleware_stack(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\middleware\errors.py", line 186, in __call__
raise exc
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\middleware\errors.py", line 164, in __call__
await self.app(scope, receive, _send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\gradio\route_utils.py", line 767, in __call__
await self.simple_response(scope, receive, send, request_headers=headers)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\gradio\route_utils.py", line 783, in simple_response
await self.app(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\middleware\exceptions.py", line 65, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
raise exc
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
await app(scope, receive, sender)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\routing.py", line 756, in __call__
await self.middleware_stack(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\routing.py", line 776, in app
await route.handle(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\routing.py", line 297, in handle
await self.app(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\routing.py", line 77, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\_exception_handler.py", line 64, in wrapped_app
raise exc
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
await app(scope, receive, sender)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\starlette\routing.py", line 72, in app
response = await func(request)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\fastapi\routing.py", line 278, in app
raw_response = await run_endpoint_function(
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\fastapi\routing.py", line 191, in run_endpoint_function
return await dependant.call(**values)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\gradio\routes.py", line 833, in queue_join
return await queue_join_helper(body, request, username)
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\gradio\routes.py", line 851, in queue_join_helper
success, event_id = await blocks._queue.push(
File "f:\Projetos\DiffusersWebUI\venv\lib\site-packages\gradio\queueing.py", line 207, in push
fn = session_state.blocks_config.fns[body.fn_index]
KeyError: 146
System Info
Gradio Environment Information:
------------------------------
Operating System: Windows
gradio version: 4.44.1
gradio_client version: 1.3.0
------------------------------------------------
gradio dependencies in your environment:
aiofiles: 23.2.1
anyio: 4.4.0
fastapi: 0.112.0
ffmpy: 0.4.0
gradio-client==1.3.0 is not installed.
httpx: 0.27.0
huggingface-hub: 0.24.5
importlib-resources: 6.4.0
jinja2: 3.1.3
markupsafe: 2.1.5
matplotlib: 3.9.0
numpy: 1.26.3
orjson: 3.10.6
packaging: 24.1
pandas: 2.2.2
pillow: 10.2.0
pydantic: 2.8.2
pydub: 0.25.1
python-multipart: 0.0.9
pyyaml: 6.0.1
ruff: 0.5.6
semantic-version: 2.10.0
tomlkit==0.12.0 is not installed.
typer: 0.12.3
typing-extensions: 4.12.2
urllib3: 2.2.2
uvicorn: 0.30.5
authlib; extra == 'oauth' is not installed.
itsdangerous; extra == 'oauth' is not installed.
gradio_client dependencies in your environment:
fsspec: 2024.2.0
httpx: 0.27.0
huggingface-hub: 0.24.5
packaging: 24.1
typing-extensions: 4.12.2
websockets: 12.0
Describe the bug
Hi guys i am getting error when events inside dynamic render are triggered and they have .then() to some function. I think is some problem of async sincronism, because some time works. I have debuged the code and i noticed that in queueing.py on push method:
when it try return the function from collection it not exists anymore. maybe because elements are removed from render before the function is called.
Have you searched existing issues? π
Reproduction
Try add a controlnet, and then remove it on X button, do it more than twice util errors happen,
My remove_controlnet.click() is calling in then update_reference_elements() function where errors occours. here is my app to test.
Screenshot
N/A
Logs
System Info
Severity
Blocking usage of gradio