dagger/dagger · error
checking for port %d/%s: %w
Error message
checking for port %d/%s: %w
What it means
Raised in portHealthChecker.Check after the exponential-backoff retry loop exhausts (or the context is cancelled) while trying to dial host:port inside the service's network namespace. It wraps the last dial error, meaning the container service port never became reachable within the backoff budget. Typically the wrapped error is connection refused, i/o timeout, or context deadline exceeded.
Source
Thrown at core/healthcheck.go:85
// NB(vito): it's a _little_ silly to dial a UDP network to see that it's
// up, since it'll be a false positive even if they're not listening yet,
// but it at least checks that we're able to resolve the container address.
conn, err := dialer.Dial(
port.Protocol.Network(),
net.JoinHostPort(d.host, fmt.Sprintf("%d", port.Port)),
)
if err != nil {
slog.Warn("port not ready", "error", err, "elapsed", retry.GetElapsedTime())
return "", err
}
endpoint := conn.RemoteAddr().String()
_ = conn.Close()
return endpoint, nil
})
}, backoff.WithContext(retry, ctx))
if err != nil {
return fmt.Errorf("checking for port %d/%s: %w", port.Port, port.Protocol.Network(), err)
}
slog.Info("port is healthy", "endpoint", endpoint)
}
return nil
}
type containerProcessExecutor interface {
Exec(context.Context, string, executor.ProcessInfo) error
}
type dockerHealthcheck struct {
args []string
origin trace.SpanContext
ctr *Container
exec containerProcessExecutor
svcID stringView on GitHub (pinned to 82ba2681db)
Solutions
- Fix the server inside the container to bind 0.0.0.0 (not localhost) on the exposed port.
- Verify the exposed port number and protocol (tcp/udp) match what the app listens on.
- Check service logs for startup crashes; fix the startup failure or increase startup time.
- Set ExperimentalSkipHealthcheck(true) only if the port is UDP or intentionally uncheckable.
- If it's just slow startup, retry with a longer context deadline.
Example fix
// before
ctr.WithExposedPort(80).AsService().Up(ctx) // app listens on 127.0.0.1:80
// after
ctr.WithExposedPort(80).WithExec([], ContainerWithExecOpts{SkipEntrypoint: false}) // app binds 0.0.0.0:80
// or, for UDP services:
WithExposedPort(53, ContainerWithExposedPortOpts{Protocol: Udp, ExperimentalSkipHealthcheck: true}) Defensive patterns
Strategy: retry
Validate before calling
// verify the app binds on 0.0.0.0 and the port is correct // e.g. inside the image: netstat -ltn | grep 0.0.0.0:8080
Type guard
var dialErr *net.OpError
if errors.As(err, &dialErr) && errors.Is(dialErr.Err, syscall.ECONNREFUSED) {
// port closed: server not listening or wrong port
} Try / catch
err := svc.Up(ctx)
if err != nil && strings.Contains(err.Error(), "checking for port") {
var opErr *net.OpError
if errors.As(err, &opErr) && errors.Is(opErr.Err, syscall.ECONNREFUSED) {
return fmt.Errorf("service never listened on the exposed port; check bind address (0.0.0.0) and logs: %w", err)
}
return err
} Prevention
- Bind service processes to 0.0.0.0, never 127.0.0.1, inside containers
- Confirm exposed port numbers/protocols match the app configuration
- Check container/service logs for startup crashes before assuming a network bug
- Use ExperimentalSkipHealthcheck(true) for UDP or non-TCP-listening services
- Allow generous context deadlines for slow-starting services
When it happens
Trigger: Starting a Dagger service (Container.up / service start) with a port whose ExperimentalSkipHealthcheck is false, where net.Dial to the container address fails for every retry until backoff gives up or ctx is done.
Common situations: The server inside the container crashed or never started, the app listens only on 127.0.0.1 instead of 0.0.0.0, wrong port mapping (container listens on 8080 but exposes 80), slow startup exceeding backoff limits, or cancelled context from an upstream timeout.
Related errors
- service digest is empty
- do init: %w
- send %s request: %w
- read SSE event from %s: %w
- %s request failed: %w
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/46b1c4fe8a1631a4.
Report an issue: GitHub.