Repository navigation
Include container logs in the error when a container fails to start - #1510
Draft
cristianrgreco wants to merge 9 commits into
Draft
cristianrgreco wants to merge 9 commits into
cristianrgreco wants to merge 9 commits into
Conversation
When a container fails its wait strategy, waitForContainer now reads the last 50 lines of its logs before removing it and appends them to the error. The logs are skipped when the error message already contains them, and a failed restart reports only the logs since the restart.
Following the logs of a stopped container can hang on Podman, which timed out the health check tests. The logs are now read without follow and before the container is stopped, so the read ends whatever state the container is in. Match the SQL Server invalid password error by substring now that the error carries the container logs.
main removed streamToString from common and made Readable a type-only import in the container client, so the merged branch no longer compiled.
…-start-6a663c # Conflicts: # packages/testcontainers/src/container-runtime/clients/container/docker-container-client.ts
cristianrgreco
marked this pull request as draft
October 13, 2026 15:55
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a container fails its wait strategy,
waitForContainerstops and removes it and rethrows the wait strategy's error, so the container's output is lost unless a log consumer was attached beforehand. The error now carries the last 50 lines of the container's logs:waitForContainerreads the log tail, then stops and removes the container as before. The read does not follow the log stream, so it ends whatever state the container is in.client.container.logsnow honoursfollow: falsefor this; it still follows by default.message(and tostack, which Node prints for uncaught errors andconsole.error). The original message stays first.abortOnContainerExitmessage (Container exited during HTTP healthCheck, last 50 logs: ...) unchanged.restart(), only logs since the restart are included, matching howWait.forLogMessagereads logs after a restart.waitForContainer:start(), the reuse path,restart(),DockerComposeEnvironment.up()and the Kafka and Redpanda modules.Tail length is 50 lines: it matches the existing HTTP
abortOnContainerExitpath, so both report the same amount and the duplicate check is exact, and it keeps error messages readable in test reporter output.Other implementations
GenericContainer.tryStart) and Go (applyLifecycleHooks→printLogs) write the full container log to the logger when a start fails. The exception does not carry it.ContainerNotRunningException) and Python (_get_container_logs_for_debuggingin the log wait) put the output in the exception message. Python truncates it.Borrowed: reporting on any start failure including timeouts (Java, Go), putting the output in the error itself (.NET, Python, and this library's HTTP path), and bounding it (Python).
Not included
Failures inside
docker compose upitself, such as adepends_on: service_healthydependency that never becomes healthy (#1210), do not go throughwaitForContainerand are unchanged.Verification
Test results
it.skip). Neither failure is caused by this change:GenericContainer restart > should restart persisting statefailed withECONNRESETon the request made after the restart.should restartfails the same way in 4 of 6 local runs againstmain's source.MSSQLServerContainer > should connect and return a query result with valid custom passwordfailed with a connection pool abort while six SQL Server containers ran at once on a 4 GB Docker VM. It passes when run on its own.abortOnContainerExitinhttp-wait-strategy.test.tspass unchanged, which covers the no-duplication case.First CI run
The first push failed two checks, both fixed in the second commit:
Tests (mssqlserver):should throw error with invalid passwordcompared the whole error message. It now matches the original message as a substring.Tests (testcontainers, 24.x, podman): the first version read the logs withfollow: trueafter stopping the container. On Podman 4.9.3 that read did not always return (two containers never got pastFetching container logs...), so the health check tests timed out. The read no longer follows. Podman is not reproduced locally (local Podman is 6.1.0), so the Podman jobs on this PR are the check for that.Red-green for the two new tests:
Before the change:
After the change:
The restart test also fails when the
sincefilter is removed (first startappears in the logs).The first test starts a container that is still running when the wait fails. With a following read it times out (
Test timed out in 180000ms), so it also guards the non-following read.New client test, before
logshonouredfollow: false:After:
Tests 4 passed (4).Not breaking
message, so substring and prefix matching keep working. Only an exact-equality match on the message of a failed start sees a difference, and only when the container produced output. One test in this repository did that (mssqlserver) and is updated here.ContainerLogsOptionsalready hadfollow; the client ignored it and always followed, which stays the default.Closes #1506