testcontainers/testcontainers-java · critical · IllegalStateException

Could not connect to Ryuk at

Error message

Could not connect to Ryuk at %s:%s

What it means

Ryuk is Testcontainers' sidecar container that reaps orphaned containers/networks/volumes after the JVM exits. In RyukResourceReaper.maybeStart the client thread signals readiness via ryukScheduledLatch; if the latch is not counted down within ryuk.timeout seconds, Testcontainers concludes the Ryuk container never became reachable and throws this IllegalStateException, failing container startup.

Solutions

  1. Verify the Ryuk image (testcontainers/ryuk:*) can be pulled: docker pull it manually / configure a registry mirror
  2. If Ryuk cannot run in your environment, set TESTCONTAINERS_RYUK_DISABLED=true (in ~/.testcontainers.properties) — you then own cleanup of stopped containers
  3. Increase the wait via testcontainers.properties `ryuk.timeout` or env TESTCONTAINERS_RYUK_TIMEOUT
  4. Check network reachability from the JVM to the Docker host/port (firewall, DOCKER_HOST misconfiguration, proxy settings)

Example fix

// before
// tests fail: Could not connect to Ryuk at 172.17.0.1:32768
// after (testcontainers.properties)
ryuk.disabled=true
// or
ryuk.timeout=120
Defensive patterns

Strategy: retry

Validate before calling

// before tests: verify Ryuk image is pullable and Docker host reachable
docker pull testcontainers/ryuk:0.11.0
nc -z <docker-host> <port> || echo "Ryuk port unreachable"

Try / catch

try {
    container.start();
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("Could not connect to Ryuk")) {
        log.warn("Ryuk unavailable; disabling and retrying", e);
        // restart with ryuk.disabled=true in testcontainers.properties
    } else throw e;
}

Prevention

When it happens

Trigger: Starting any container when Ryuk is enabled and: the Ryuk image cannot be pulled (offline/private registry), the host port for Ryuk is not reachable (firewall, remote Docker host without exposed port), Ryuk fails to boot (incompatible image/arch), or the configured timeout is too short.

Common situations: CI runners with restrictive networking to remote Docker (DOCKER_HOST over ssh/tcp); air-gapped environments without the testcontainers/ryuk image in a local mirror; enterprise proxies blocking the connection; slow image pulls exceeding the default timeout.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/f77b0e73851f5834. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/testcontainers/utility/RyukResourceReaper.java:132

                                    } else {
                                        log.debug("Didn't receive 'ACK' from Ryuk. Will retry to send filters.");
                                    }
                                }
                            }
                        } catch (IOException e) {
                            log.warn("Can not connect to Ryuk at {}:{}", host, ryukPort, e);
                        }
                    });
                }
            },
            "testcontainers-ryuk"
        );
        kiraThread.setDaemon(true);
        kiraThread.start();
        // We need to wait before we can start any containers to make sure that we delete them
        if (!ryukScheduledLatch.await(TestcontainersConfiguration.getInstance().getRyukTimeout(), TimeUnit.SECONDS)) {
            log.error("Timed out waiting for Ryuk container to start. Ryuk's logs:\n{}", ryukContainer.getLogs());
            throw new IllegalStateException(String.format("Could not connect to Ryuk at %s:%s", host, ryukPort));
        }
    }
}

View on GitHub (pinned to 8e549514e3)