Skip to content

fix(tests): Integration tests are failing in the CI system: "RuntimeE…#1010

Merged
mpawlow merged 2 commits into
mainfrom
mp/fix/GH-1009-failing-integration-tests
Feb 24, 2026
Merged

fix(tests): Integration tests are failing in the CI system: "RuntimeE…#1010
mpawlow merged 2 commits into
mainfrom
mp/fix/GH-1009-failing-integration-tests

Conversation

@mpawlow

@mpawlow mpawlow commented Feb 23, 2026

Copy link
Copy Markdown
Collaborator

…rror: Event loop is closed"

Issue

Commit 1

Summary:

Fix RuntimeError: Event loop is closed in OpenAI client initialization by separating the HTTP/2 probe from production client creation. The probe thread previously returned the AsyncOpenAI client itself, leaving its SSL connections bound to a closed event loop. The production client is now created after the thread exits, in the caller's event loop.

Details

The HTTP/2 probe ran in a background thread with its own event loop, created an AsyncOpenAI client, and returned it directly. Closing the thread's event loop while the client still held open keep-alive SSL connections caused RuntimeError: Event loop is closed whenever the client was later used in the caller's (different) event loop.

Bug Fix: Decouple probe from production client lifetime

  • Rename probe_and_initialize() → probe_http2(), which now returns a bool instead of an AsyncOpenAI client
  • Explicitly close the probe client in a finally block so all connections are drained before the thread's event loop is closed
  • Create the production AsyncOpenAI client after the thread exits, in the caller's event loop context, so its connections bind to the correct running loop

HTTP/2 Fallback Logic

  • Preserve HTTP/2 vs HTTP/1.1 selection: use_http2=True creates a default AsyncOpenAI(); use_http2=False creates one with an explicit httpx.AsyncClient(http2=False) transport
  • No change to probe timeout (5s) or overall initialization timeout (15s)

Commit 2

Summary

Fix two CI-only failures caused by environment variable bleed-through in the CI test pipeline: Docker containers receiving localhost as the OpenSearch hostname (instead of the opensearch service name), and the backend crashing with invalid literal for int() with base 10: '' due
to empty Langflow retry env vars being injected into the container.

Details

The GitHub Actions workflow sets OPENSEARCH_HOST=localhost as a step-level env var so the in-process pytest backend can reach OpenSearch via Docker port mapping. This bled into docker-compose, overriding the opensearch service-name default and breaking all OpenSearch calls from inside the backend and Langflow containers. Separately, LANGFLOW_KEY_RETRIES and LANGFLOW_KEY_RETRY_DELAY had no :-default fallbacks in docker-compose.yml, so when unset in CI they were injected as empty strings, causing int("") to raise ValueError inside get_langflow_api_key().

CI Configuration: Docker container startup

  • Pin OPENSEARCH_HOST=opensearch when invoking docker-compose up in the
    test-ci and test-ci-local Makefile targets, isolating it from the
    OPENSEARCH_HOST=localhost value the surrounding CI shell sets for pytest

docker-compose.yml: Environment variable defaults

  • Add :-15 default for LANGFLOW_KEY_RETRIES so unset env produces "15"
    rather than an empty string that crashes int() in settings.py
  • Add :-2.0 default for LANGFLOW_KEY_RETRY_DELAY for the same reason;
    defaults match the hardcoded fallbacks already in settings.py:227-228

…rror: Event loop is closed"

Issue

- #1009

Summary:

Fix RuntimeError: Event loop is closed in OpenAI client initialization by separating the HTTP/2 probe from production client creation. The probe thread previously returned the AsyncOpenAI client itself, leaving its SSL connections bound to a closed event loop. The production
client is now created after the thread exits, in the caller's event loop.

Details:

The HTTP/2 probe ran in a background thread with its own event loop,
created an AsyncOpenAI client, and returned it directly. Closing the
thread's event loop while the client still held open keep-alive SSL
connections caused `RuntimeError: Event loop is closed` whenever the
client was later used in the caller's (different) event loop.

Bug Fix: Decouple probe from production client lifetime

- Rename probe_and_initialize() → probe_http2(), which now returns a
  bool instead of an AsyncOpenAI client
- Explicitly close the probe client in a finally block so all
  connections are drained before the thread's event loop is closed
- Create the production AsyncOpenAI client after the thread exits,
  in the caller's event loop context, so its connections bind to the
  correct running loop

HTTP/2 Fallback Logic

- Preserve HTTP/2 vs HTTP/1.1 selection: use_http2=True creates a
  default AsyncOpenAI(); use_http2=False creates one with an explicit
  httpx.AsyncClient(http2=False) transport
- No change to probe timeout (5s) or overall initialization timeout (15s)
@mpawlow mpawlow self-assigned this Feb 23, 2026
…rror: Event loop is closed"

Issue

- #1009

Summary:

Fix two CI-only failures caused by environment variable bleed-through in the CI test pipeline: Docker containers receiving localhost as the OpenSearch hostname (instead of the opensearch service name), and the backend crashing with invalid literal for int() with base 10: '' due
to empty Langflow retry env vars being injected into the container.

Detials:

The GitHub Actions workflow sets OPENSEARCH_HOST=localhost as a step-level
env var so the in-process pytest backend can reach OpenSearch via Docker
port mapping. This bled into docker-compose, overriding the opensearch
service-name default and breaking all OpenSearch calls from inside the
backend and Langflow containers. Separately, LANGFLOW_KEY_RETRIES and
LANGFLOW_KEY_RETRY_DELAY had no :-default fallbacks in docker-compose.yml,
so when unset in CI they were injected as empty strings, causing
int("") to raise ValueError inside get_langflow_api_key().

CI Configuration: Docker container startup

- Pin OPENSEARCH_HOST=opensearch when invoking docker-compose up in the
  test-ci and test-ci-local Makefile targets, isolating it from the
  OPENSEARCH_HOST=localhost value the surrounding CI shell sets for pytest

docker-compose.yml: Environment variable defaults

- Add :-15 default for LANGFLOW_KEY_RETRIES so unset env produces "15"
  rather than an empty string that crashes int() in settings.py
- Add :-2.0 default for LANGFLOW_KEY_RETRY_DELAY for the same reason;
  defaults match the hardcoded fallbacks already in settings.py:227-228

@edwinjosechittilappilly edwinjosechittilappilly left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@edwinjosechittilappilly

Copy link
Copy Markdown
Collaborator

Thanks @mpawlow Good one!

Lets merge this so that Other PRs could be unblocked in tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes CI integration test failures by addressing an async OpenAI client lifecycle bug and hardening CI/container environment variable behavior.

Changes:

  • Refactors the OpenAI HTTP/2 probe to return only a boolean and creates the production AsyncOpenAI client in the caller’s event loop (avoids cross-loop “Event loop is closed” errors).
  • Adds safe defaults for LANGFLOW_KEY_RETRIES / LANGFLOW_KEY_RETRY_DELAY in docker-compose.yml to prevent empty-string parsing failures in CI.
  • Pins OPENSEARCH_HOST=opensearch for docker-compose up in CI Makefile targets to avoid CI env-var bleed-through (localhost inside containers).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/config/settings.py Decouples HTTP/2 probe from production client creation to avoid cross-event-loop transport usage.
docker-compose.yml Provides defaults for Langflow retry env vars to prevent int("") / float("") failures.
Makefile Forces container-side OpenSearch hostname to opensearch during CI compose startup.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/config/settings.py
Comment thread src/config/settings.py
@mpawlow mpawlow merged commit 924c569 into main Feb 24, 2026
8 checks passed
@mpawlow mpawlow deleted the mp/fix/GH-1009-failing-integration-tests branch February 24, 2026 13:23
@edwinjosechittilappilly edwinjosechittilappilly added the bug 🔴 Something isn't working. label Feb 26, 2026
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

Successfully merging this pull request may close these issues.

3 participants