Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api error handler #8662

Merged
merged 1 commit into from
Mar 25, 2023
Merged

Conversation

vladmandic
Copy link
Collaborator

@vladmandic vladmandic commented Mar 15, 2023

with increased usage via api, there are quite a few issues where user has no idea what is the problem or how to troubleshoot it due to error messages coming from fastapi/starlette/anyio could not be more crtptic

this pr replaces fastapi exception handler with a custom one (both using pretty-printed version or normal python traceback are supported)

note: pretty-print uses rich as formatter which is same as accelerate, so its no a new requirement, i just wanted to be explicit about loading it and have a fallback if its not available

global handler?

if there is interest, i can extend this same exception handler to cover entire webui
(api always needs a separate handler anyhow due to how fastapi works internally)

new api error handling

clear error message and source

API error: GET: http://127.0.0.1:7860/sdapi/v1/progress {'error': 'NameError', 'detail': '', 'body': '', 'errors': "name 'unknown' is not defined"}

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/vlado/dev/automatic/modules/api/api.py:136 in exception_handling                           │
│                                                                                                  │
│   135 │   │   try:                                                                               │
│ ❱ 136 │   │   │   return await call_next(request)                                                │
│   137 │   │   except Exception as e:                                                             │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │        call_next = <function BaseHTTPMiddleware.__call__.<locals>.call_next at               │ │
│ │                    0x7f94a39ac280>                                                           │ │
│ │                e = NameError("name 'uknown' is not defined")                                 │ │
│ │ handle_exception = <function api_middleware.<locals>.handle_exception at 0x7f94a3919480>     │ │
│ │          request = <starlette.requests.Request object at 0x7f94a39a2650>                     │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/base.py:84 in call_next     │
│                                                                                                  │
│                                     ... 19 frames hidden ...                                     │
│                                                                                                  │
│ /home/vlado/.local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py:867 in run           │
│                                                                                                  │
│ /home/vlado/dev/automatic/modules/api/api.py:403 in progressapi                                  │
│                                                                                                  │
│   402 │   │   if shared.state.job_count == 0:                                                    │
│ ❱ 403 │   │   │   return ProgressResponse(uknown, progress=0, eta_relative=0, state=shared.sta   │
│   404                                                                                            │
│                                                                                                  │
│ ╭────────────────────── locals ──────────────────────╮                                           │
│ │  req = ProgressRequest(skip_current_image=False)   │                                           │
│ │ self = <api.py.ApiHijack object at 0x7f94a3ab46a0> │                                           │
│ ╰────────────────────────────────────────────────────╯                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
NameError: name 'uknown' is not defined

old api error handling

unreadable and whats worse, it doesn't even show where error comes from

ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/home/vlado/.local/lib/python3.10/site-packages/anyio/streams/memory.py", line 94, in receive
    return self.receive_nowait()
  File "/home/vlado/.local/lib/python3.10/site-packages/anyio/streams/memory.py", line 89, in receive_nowait
    raise WouldBlock
anyio.WouldBlock

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 78, in call_next
    message = await recv_stream.receive()
  File "/home/vlado/.local/lib/python3.10/site-packages/anyio/streams/memory.py", line 114, in receive
    raise EndOfStream
anyio.EndOfStream

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/vlado/.local/lib/python3.10/site-packages/uvicorn/protocols/http/h11_impl.py", line 407, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
  File "/home/vlado/.local/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py", line 78, in __call__
    return await self.app(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/fastapi/applications.py", line 273, in __call__
    await super().__call__(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/applications.py", line 120, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 184, in __call__
    raise exc
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 108, in __call__
    response = await self.dispatch_func(request, call_next)
  File "/home/vlado/dev/automatic/modules/api/api.py", line 96, in log_and_time
    res: Response = await call_next(req)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 84, in call_next
    raise app_exc
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/base.py", line 70, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/cors.py", line 84, in __call__
    await self.app(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/gzip.py", line 24, in __call__
    await responder(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/gzip.py", line 44, in __call__
    await self.app(scope, receive, self.send_with_gzip)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 79, in __call__
    raise exc
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 68, in __call__
    await self.app(scope, receive, sender)
  File "/home/vlado/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
    raise e
  File "/home/vlado/.local/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
    await self.app(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/routing.py", line 716, in __call__
    await route.handle(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/routing.py", line 276, in handle
    await self.app(scope, receive, send)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/routing.py", line 66, in app
    response = await func(request)
  File "/home/vlado/.local/lib/python3.10/site-packages/fastapi/routing.py", line 237, in app
    raw_response = await run_endpoint_function(
  File "/home/vlado/.local/lib/python3.10/site-packages/fastapi/routing.py", line 165, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "/home/vlado/.local/lib/python3.10/site-packages/starlette/concurrency.py", line 41, in run_in_threadpool
    return await anyio.to_thread.run_sync(func, *args)
  File "/home/vlado/.local/lib/python3.10/site-packages/anyio/to_thread.py", line 31, in run_sync
    return await get_asynclib().run_sync_in_worker_thread(
  File "/home/vlado/.local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 937, in run_sync_in_worker_thread
    return await future
  File "/home/vlado/.local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 867, in run
    result = context.run(func, *args)
  File "/home/vlado/dev/automatic/modules/api/api.py", line 368, in progressapi
    return ProgressResponse(unknown, progress=0, eta_relative=0, state=shared.state.dict(), textinfo=shared.state.textinfo)
NameError: name 'unknown' is not defined

@AUTOMATIC1111 AUTOMATIC1111 merged commit a03536f into AUTOMATIC1111:master Mar 25, 2023
@vladmandic vladmandic deleted the api-handler branch March 25, 2023 11:30
brkirch pushed a commit to brkirch/stable-diffusion-webui that referenced this pull request Apr 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants