testcontainers/testcontainers-java · warning

Can not connect to Ryuk at

Error message

Can not connect to Ryuk at {}:{}

What it means

RyukResourceReaper.maybeStart opens a socket to the Ryuk sidecar container to register cleanup filters. When connecting fails with an IOException, this warning is logged (inside an executor thread) and filter registration is retried/abandoned. Ryuk handles automatic container cleanup after the JVM exits; failure to connect means automatic reaping may not work for this session.

Solutions

  1. Check the Ryuk container status (`docker ps | grep ryuk`) and its logs for startup failures
  2. Set TESTCONTAINERS_HOST_OVERRIDE or verify ryuk.container.image / TESTCONTAINERS_RYUK_DISABLED settings in ~/.testcontainers.properties
  3. Ensure the host running tests can reach the port Ryuk is mapped to on the Docker host (critical for remote Docker)
  4. Update the Testcontainers version — newer releases have more robust Ryuk connection/retry handling
  5. Set TESTCONTAINERS_RYUK_DISABLED=true as a workaround and clean up containers manually

Example fix

// before: relying on Ryuk behind an unreachable remote Docker host
default behavior (ryuk enabled)
// after: ~/.testcontainers.properties
ryuk.disabled=true
// and add a @AfterAll stopAll in tests:
@AfterAll static void cleanup() { RyukResourceReaper.instance().performCleanup(); }
Defensive patterns

Strategy: retry

Validate before calling

// probe reachability before relying on Ryuk
try (Socket s = new Socket()) { s.connect(new InetSocketAddress(ryukHost, ryukPort), 2000); return true; } catch (IOException e) { return false; }

Try / catch

try (Socket socket = new Socket(host, ryukPort)) { /* register filters */ } catch (IOException e) { log.warn("Ryuk unreachable, falling back to manual cleanup"); }

Prevention

When it happens

Trigger: Ryuk container not started or crashed; TESTCONTAINERS_RYUK_DISABLED misconfiguration; network unreachable between JVM and Ryuk (custom networks, firewall, remote Docker host); Ryuk port not yet exposed when the first filter registration happens.

Common situations: Remote Docker (DOCKER_HOST over TCP/ssh) where the mapped Ryuk port isn't routable from the client; corporate proxies blocking the connection; Ryuk image pull failure leaving the helper container down; IPv6 vs IPv4 mismatch on localhost.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


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

Appendix: source

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

                                            ResourceReaper.DEATH_NOTE.wait(1_000);
                                            continue;
                                        } catch (InterruptedException e) {
                                            throw new RuntimeException(e);
                                        }
                                    }
                                    List<Map.Entry<String, String>> filters = ResourceReaper.DEATH_NOTE.get(index);
                                    boolean isAcknowledged = registry.register(filters);
                                    if (isAcknowledged) {
                                        log.debug("Received 'ACK' from Ryuk");
                                        ryukScheduledLatch.countDown();
                                        index++;
                                    } 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)