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

[bug]: httpcore.RemoteProtocolError: Server disconnected without sending a response. #123

Open
R0Wi opened this issue Jan 2, 2025 · 0 comments
Labels
bug Something isn't working

Comments

@R0Wi
Copy link
Member

R0Wi commented Jan 2, 2025

Describe the bug
When using the context chat function, I (sometimes) get the Exception: httpcore.RemoteProtocolError: Server disconnected without sending a response.

To Reproduce
Steps to reproduce the behavior:

  1. Go to Context Chat in NC frontend
  2. Type in a question
  3. Click on "Context Chat"

Expected behavior
A clear and concise description of what you expected to happen.

Server logs (if applicable)

{"reqId":"2zSA1egPbXxBNR6l8KVy","level":3,"time":"2025-01-02T19:32:36+00:00","remoteAddr":"","user":"--","app":"no app in context","method":"","url":"--","message":"Unknown error while processing TaskProcessing task","userAgent":"--","version":"30.0.4.1","exception":{"Exception":"RuntimeException","Message":"Error received from Context Chat Backend (ExApp) with status code 500: unknown error","Code":0,"Trace":[{"file":"/var/www/html/custom_apps/context_chat/lib/Service/LangRopeService.php","line":311,"function":"requestToExApp","class":"OCA\\ContextChat\\Service\\LangRopeService","type":"->","args":["/query","POST",{"query":"PROMPT","userId":"usr","useContext":true}]},{"file":"/var/www/html/custom_apps/context_chat/lib/TaskProcessing/ContextChatProvider.php","line":118,"function":"query","class":"OCA\\ContextChat\\Service\\LangRopeService","type":"->","args":["usr","WPROMPT"]},{"file":"/var/www/html/lib/private/TaskProcessing/Manager.php","line":810,"function":"process","class":"OCA\\ContextChat\\TaskProcessing\\ContextChatProvider","type":"->","args":["usr",{"prompt":"PROMPT","scopeType":"none","scopeList":[],"scopeListMeta":"[]"},{"__class__":"Closure"}]},{"file":"/var/www/html/lib/private/TaskProcessing/SynchronousBackgroundJob.php","line":54,"function":"processTask","class":"OC\\TaskProcessing\\Manager","type":"->","args":[{"__class__":"OCP\\TaskProcessing\\Task"},{"__class__":"OCA\\ContextChat\\TaskProcessing\\ContextChatProvider"}]},{"file":"/var/www/html/lib/public/BackgroundJob/Job.php","line":61,"function":"run","class":"OC\\TaskProcessing\\SynchronousBackgroundJob","type":"->","args":[null]},{"file":"/var/www/html/lib/public/BackgroundJob/QueuedJob.php","line":43,"function":"start","class":"OCP\\BackgroundJob\\Job","type":"->","args":[{"__class__":"OC\\BackgroundJob\\JobList"}]},{"file":"/var/www/html/lib/public/BackgroundJob/QueuedJob.php","line":29,"function":"start","class":"OCP\\BackgroundJob\\QueuedJob","type":"->","args":[{"__class__":"OC\\BackgroundJob\\JobList"}]},{"file":"/var/www/html/core/Command/Background/JobWorker.php","line":129,"function":"execute","class":"OCP\\BackgroundJob\\QueuedJob","type":"->","args":[{"__class__":"OC\\BackgroundJob\\JobList"}]},{"file":"/var/www/html/3rdparty/symfony/console/Command/Command.php","line":326,"function":"execute","class":"OC\\Core\\Command\\Background\\JobWorker","type":"->","args":[{"__class__":"Symfony\\Component\\Console\\Input\\ArgvInput"},{"__class__":"Symfony\\Component\\Console\\Output\\ConsoleOutput"}]},{"file":"/var/www/html/core/Command/Base.php","line":161,"function":"run","class":"Symfony\\Component\\Console\\Command\\Command","type":"->","args":[{"__class__":"Symfony\\Component\\Console\\Input\\ArgvInput"},{"__class__":"Symfony\\Component\\Console\\Output\\ConsoleOutput"}]},{"file":"/var/www/html/3rdparty/symfony/console/Application.php","line":1078,"function":"run","class":"OC\\Core\\Command\\Base","type":"->","args":[{"__class__":"Symfony\\Component\\Console\\Input\\ArgvInput"},{"__class__":"Symfony\\Component\\Console\\Output\\ConsoleOutput"}]},{"file":"/var/www/html/3rdparty/symfony/console/Application.php","line":324,"function":"doRunCommand","class":"Symfony\\Component\\Console\\Application","type":"->","args":[{"__class__":"OC\\Core\\Command\\Background\\JobWorker"},{"__class__":"Symfony\\Component\\Console\\Input\\ArgvInput"},{"__class__":"Symfony\\Component\\Console\\Output\\ConsoleOutput"}]},{"file":"/var/www/html/3rdparty/symfony/console/Application.php","line":175,"function":"doRun","class":"Symfony\\Component\\Console\\Application","type":"->","args":[{"__class__":"Symfony\\Component\\Console\\Input\\ArgvInput"},{"__class__":"Symfony\\Component\\Console\\Output\\ConsoleOutput"}]},{"file":"/var/www/html/lib/private/Console/Application.php","line":183,"function":"run","class":"Symfony\\Component\\Console\\Application","type":"->","args":[{"__class__":"Symfony\\Component\\Console\\Input\\ArgvInput"},{"__class__":"Symfony\\Component\\Console\\Output\\ConsoleOutput"}]},{"file":"/var/www/html/console.php","line":87,"function":"run","class":"OC\\Console\\Application","type":"->","args":[{"__class__":"Symfony\\Component\\Console\\Input\\ArgvInput"}]},{"file":"/var/www/html/occ","line":11,"args":["/var/www/html/console.php"],"function":"require_once"}],"File":"/var/www/html/custom_apps/context_chat/lib/Service/LangRopeService.php","Line":166,"message":"Unknown error while processing TaskProcessing task","exception":[],"CustomMessage":"Unknown error while processing TaskProcessing task"},"id":"6776ef57ad2aa"}

{"reqId":"2zSA1egPbXxBNR6l8KVy","level":2,"time":"2025-01-02T19:32:36+00:00","remoteAddr":"","user":"--","app":"no app in context","method":"","url":"--","message":"A TaskProcessing context_chat:context_chat task with id 73 failed with the following message: Error received from Context Chat Backend (ExApp) with status code 500: unknown error","userAgent":"--","version":"30.0.4.1","data":[],"id":"6776ef57ad27f"}

Context Chat Backend logs (if applicable, from the docker container)

id=74 status='STATUS_SCHEDULED' output=None
id=74 status='STATUS_RUNNING' output=None
id=74 status='STATUS_RUNNING' output=None
original traceback: Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/httpx/_transports/default.py", line 101, in map_httpcore_exceptions
    yield
  File "/usr/local/lib/python3.11/dist-packages/httpx/_transports/default.py", line 250, in handle_request
    resp = self._pool.handle_request(req)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpcore/_sync/connection_pool.py", line 256, in handle_request
    raise exc from None
  File "/usr/local/lib/python3.11/dist-packages/httpcore/_sync/connection_pool.py", line 236, in handle_request
    response = connection.handle_request(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpcore/_sync/connection.py", line 103, in handle_request
    return self._connection.handle_request(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpcore/_sync/http11.py", line 136, in handle_request
    raise exc
  File "/usr/local/lib/python3.11/dist-packages/httpcore/_sync/http11.py", line 106, in handle_request
    ) = self._receive_response_headers(**kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpcore/_sync/http11.py", line 177, in _receive_response_headers
    event = self._receive_event(timeout=timeout)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpcore/_sync/http11.py", line 231, in _receive_event
    raise RemoteProtocolError(msg)
httpcore.RemoteProtocolError: Server disconnected without sending a response.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/app/context_chat_backend/utils.py", line 94, in exception_wrap
    resconn.send({ 'value': fun(*args, **kwargs), 'error': None })
                            ^^^^^^^^^^^^^^^^^^^^
  File "/app/context_chat_backend/chain/one_shot.py", line 70, in process_context_query
    output = llm.invoke(
             ^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/langchain_core/language_models/llms.py", line 390, in invoke
    self.generate_prompt(
  File "/usr/local/lib/python3.11/dist-packages/langchain_core/language_models/llms.py", line 755, in generate_prompt
    return self.generate(prompt_strings, stop=stop, callbacks=callbacks, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/langchain_core/language_models/llms.py", line 950, in generate
    output = self._generate_helper(
             ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/langchain_core/language_models/llms.py", line 792, in _generate_helper
    raise e
  File "/usr/local/lib/python3.11/dist-packages/langchain_core/language_models/llms.py", line 779, in _generate_helper
    self._generate(
  File "/usr/local/lib/python3.11/dist-packages/langchain_core/language_models/llms.py", line 1502, in _generate
    self._call(prompt, stop=stop, run_manager=run_manager, **kwargs)
  File "/app/context_chat_backend/models/nc_texttotext.py", line 85, in _call
    i += 1
           
  File "/usr/local/lib/python3.11/dist-packages/nc_py_api/nextcloud.py", line 144, in ocs
    return self._session.ocs(method, path, content=content, json=json, params=params, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/nc_py_api/_session.py", line 207, in ocs
    response = self.adapter.request(
               ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpx/_client.py", line 825, in request
    return self.send(request, auth=auth, follow_redirects=follow_redirects)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpx/_client.py", line 914, in send
    response = self._send_handling_auth(
               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpx/_client.py", line 942, in _send_handling_auth
    response = self._send_handling_redirects(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpx/_client.py", line 979, in _send_handling_redirects
    response = self._send_single_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpx/_client.py", line 1014, in _send_single_request
    response = transport.handle_request(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/httpx/_transports/default.py", line 249, in handle_request
    with map_httpcore_exceptions():
  File "/usr/lib/python3.11/contextlib.py", line 158, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/usr/local/lib/python3.11/dist-packages/httpx/_transports/default.py", line 118, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.RemoteProtocolError: Server disconnected without sending a response.

TRACE:    172.22.0.8:38990 - ASGI [17] Send {'type': 'http.response.start', 'status': 500, 'headers': '<...>'}
INFO:     172.22.0.8:38990 - "POST /query HTTP/1.1" 500 Internal Server Error
TRACE:    172.22.0.8:38990 - ASGI [17] Send {'type': 'http.response.body', 'body': '<3521 bytes>'}
TRACE:    172.22.0.8:38990 - ASGI [17] Raised exception
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/dist-packages/uvicorn/protocols/http/h11_impl.py", line 403, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/uvicorn/middleware/message_logger.py", line 84, in __call__
    raise exc from None
  File "/usr/local/lib/python3.11/dist-packages/uvicorn/middleware/message_logger.py", line 80, in __call__
    await self.app(scope, inner_receive, inner_send)
  File "/usr/local/lib/python3.11/dist-packages/fastapi/applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/applications.py", line 113, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/middleware/errors.py", line 187, in __call__
    raise exc
  File "/usr/local/lib/python3.11/dist-packages/starlette/middleware/errors.py", line 165, in __call__
    await self.app(scope, receive, _send)
  File "/app/context_chat_backend/ocs_utils.py", line 79, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/middleware/exceptions.py", line 62, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    raise exc
  File "/usr/local/lib/python3.11/dist-packages/starlette/_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
  File "/usr/local/lib/python3.11/dist-packages/starlette/routing.py", line 715, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/routing.py", line 735, in app
    await route.handle(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/routing.py", line 288, in handle
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/routing.py", line 76, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  File "/usr/local/lib/python3.11/dist-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    raise exc
  File "/usr/local/lib/python3.11/dist-packages/starlette/_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
  File "/usr/local/lib/python3.11/dist-packages/starlette/routing.py", line 73, in app
    response = await f(request)
               ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/fastapi/routing.py", line 301, in app
    raw_response = await run_endpoint_function(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/fastapi/routing.py", line 214, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/starlette/concurrency.py", line 39, in run_in_threadpool
    return await anyio.to_thread.run_sync(func, *args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/anyio/to_thread.py", line 56, in run_sync
    return await get_async_backend().run_sync_in_worker_thread(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/anyio/_backends/_asyncio.py", line 2505, in run_sync_in_worker_thread
    return await future
           ^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/anyio/_backends/_asyncio.py", line 1005, in run
    result = context.run(func, *args)
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/context_chat_backend/controller.py", line 163, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/app/context_chat_backend/controller.py", line 390, in _
    return execute_query(query)
           ^^^^^^^^^^^^^^^^^^^^
  File "/app/context_chat_backend/controller.py", line 379, in execute_query
    return exec_in_proc(target=target, args=args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/context_chat_backend/utils.py", line 117, in exec_in_proc
    raise result['error']
httpx.RemoteProtocolError: Server disconnected without sending a response.
TRACE:    172.22.0.8:38990 - HTTP connection lost

Setup Details (please complete the following information):

  • Nextcloud Version: 30.0
  • AppAPI Version: 4.0.3
  • Context Chat PHP Version 4.0.1
  • Context Chat Backend Version 4.0.1
  • Nextcloud deployment method: Docker
  • Context Chat Backend deployment method: [Docker

Additional context
The issue is not always reproducible. I can only tell that it happens in the /ocs/v1.php/taskprocessing/task/ call. I was able to find a (ugly) workaround by catching the raised exception:

response = nc.ocs("GET", f"/ocs/v1.php/taskprocessing/task/{task.id}")

        try:
            task = Response.model_validate(response).task
            print(task)

            i = 0
            # wait for 30 minutes
            while task.status != "STATUS_SUCCESSFUL" and task.status != "STATUS_FAILED" and i < 60 * 6:
                time.sleep(5)
                i += 1
                try:
                    response = nc.ocs("GET", f"/ocs/v1.php/taskprocessing/task/{task.id}")
                except RemoteProtocolError as e:
                    print(e)
                    continue
                task = Response.model_validate(response).task
                print(task)
        except ValidationError as e:
            raise LlmException("Failed to parse Nextcloud TaskProcessing task result") from e

One of the outputs I captured after this adjustment from the backend:

id=80 status='STATUS_SCHEDULED' output=None
id=80 status='STATUS_RUNNING' output=None
TRACE:    172.22.0.8:52810 - HTTP connection lost
id=80 status='STATUS_RUNNING' output=None
id=80 status='STATUS_RUNNING' output=None
Server disconnected without sending a response.
id=80 status='STATUS_RUNNING' output=None
id=80 status='STATUS_RUNNING' output=None
id=80 status='STATUS_SUCCESSFUL' output={'output': ...

You can see that the (temporary) loss of the connection from the chat backend to the NC server (also hosted in Docker) doesn't break the full process. I think that putting some "retry mechanism" in place here makes sense somehow.

I found a similar issue here where they also worked around this by retrying the request.

@R0Wi R0Wi added the bug Something isn't working label Jan 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant