Describe the bug
When using an HttpWaitStrategy in DockerContainer.waiting_for and the container image respond with an error code, the underlying HttpError is not correctly handled, leaking a file descriptor.
To Reproduce
Example with the https://hub.docker.com/r/typesense/typesense image, but should work with any image providing a HTTP server that takes a few seconds to start:
# mre.py
from testcontainers.core.container import DockerContainer
from testcontainers.core.wait_strategies import HttpWaitStrategy
print("starting")
with (
DockerContainer("typesense/typesense:30.2", command="--data-dir /home --api-key=whatever --enable-cors")
.with_exposed_ports(8108)
.waiting_for(HttpWaitStrategy(8108, "/health").for_status_code(200))
):
print("ok")
$ python -Werror::ResourceWarning mre.py
starting
Exception ignored while calling deallocator <function _TemporaryFileCloser.__del__ at 0x101984880>:
Traceback (most recent call last):
File "/Users/loic/.local/share/uv/python/cpython-3.14.4-macos-aarch64-none/lib/python3.14/tempfile.py", line 484, in __del__
_warnings.warn(self.warn_message, ResourceWarning)
ResourceWarning: Implicitly cleaning up <HTTPError 503: ''>
ok
Root Cause / fix
The issue is in
|
def _handle_http_error(self, error: Union[URLError, HTTPError]) -> bool: |
|
"""Handle HTTP errors and return True if error is acceptable.""" |
|
if isinstance(error, HTTPError) and ( |
|
error.code in self._status_codes |
|
or (self._status_code_predicate and self._status_code_predicate(error.code)) |
|
): |
|
return True |
|
logger.debug(f"HTTP request failed: {error!s}") |
|
return False |
|
|
HttpError holds a reference to a (temporary) file storing the HTTP response, so it must be handled in a context manager to safely clean the file when the error is discarded.
Fixed MRE:
# mre.py
from contextlib import nullcontext
from typing import Union
from urllib.error import HTTPError, URLError
from testcontainers.core.container import DockerContainer
from testcontainers.core.wait_strategies import HttpWaitStrategy
class _FixedHttpWaitStrategy(HttpWaitStrategy):
def _handle_http_error(self, error: Union[URLError, HTTPError]) -> bool:
with error if isinstance(error, HTTPError) else nullcontext(error):
return super()._handle_http_error(error)
print("starting")
with (
DockerContainer("typesense/typesense:30.2", command="--data-dir /home --api-key=whatever --enable-cors")
.with_exposed_ports(8108)
.waiting_for(_FixedHttpWaitStrategy(8108, "/health").for_status_code(200))
):
print("ok")
Runtime environment
- MacOS 26.6.2
- Python 3.14.4
- testcontainers 4.14.2
I can work on a PR if you'd like!
Describe the bug
When using an
HttpWaitStrategyinDockerContainer.waiting_forand the container image respond with an error code, the underlyingHttpErroris not correctly handled, leaking a file descriptor.To Reproduce
Example with the https://hub.docker.com/r/typesense/typesense image, but should work with any image providing a HTTP server that takes a few seconds to start:
Root Cause / fix
The issue is in
testcontainers-python/src/testcontainers/core/wait_strategies.py
Lines 428 to 437 in 5c70d54
HttpErrorholds a reference to a (temporary) file storing the HTTP response, so it must be handled in a context manager to safely clean the file when the error is discarded.Fixed MRE:
Runtime environment
I can work on a PR if you'd like!