micro/go-micro · error
could not dial ${addr}
Error message
could not dial ${addr} What it means
The in-memory transport only allows dialing addresses that have a registered listener in the same process. Dial looks up m.listeners[addr]; if nothing is listening on that exact address string it returns 'could not dial <addr>'. Because it's process-local, a mismatched address string is the usual culprit.
Source
Thrown at transport/memory.go:188
exit: c.exit,
ssend: c.ssend,
srecv: c.srecv,
local: c.Remote(),
remote: c.Local(),
timeout: m.topts.Timeout,
ctx: m.topts.Context,
})
}
}
}
func (m *memoryTransport) Dial(addr string, opts ...DialOption) (Client, error) {
m.RLock()
defer m.RUnlock()
listener, ok := m.listeners[addr]
if !ok {
return nil, errors.New("could not dial " + addr)
}
var options DialOptions
for _, o := range opts {
o(&options)
}
creader, swriter := io.Pipe()
sreader, cwriter := io.Pipe()
client := &memoryClient{
&memorySocket{
server: false,
csend: gob.NewEncoder(cwriter),
crecv: gob.NewDecoder(creader),
ssend: gob.NewEncoder(swriter),
srecv: gob.NewDecoder(sreader), exit: make(chan bool),
lexit: listener.exit,View on GitHub (pinned to 24529f1404)
Solutions
- Ensure Listen(addr) completed and use the address it returns (it resolves port 0 and adds missing ports) as the Dial target
- Make host/port strings match exactly after HostPort normalization (same host, same resolved port)
- In tests, capture the listener's addr via server-side socket or the returned listener before dialing; add synchronization so Listen happens before Dial
Example fix
// before
server.Listen(":0") // binds random port
c.Dial("localhost:0") // could not dial localhost:0
// after
l, err := server.Listen(":0")
addr := l.Addr() // actual resolved host:port
c.Dial(addr) Defensive patterns
Strategy: validation
Validate before calling
l, err := m.Listen(":0")
if err != nil { return err }
addr := l.Addr() // use this exact addr for Dial Try / catch
c, err := m.Dial(addr)
if err != nil && strings.HasPrefix(err.Error(), "could not dial ") {
// re-check listener is up, use listener.Addr()
} Prevention
- Always dial the address returned by Listen, never the raw configured one
- Synchronize tests so Listen completes before Dial
- Prefer ephemeral ports (":0") with the resolved addr
When it happens
Trigger: transport.Dial(addr) before the corresponding server called Listen(addr); address strings that differ after Listen normalized them via mnet.HostPort (e.g. '127.0.0.1:0' vs the resolved '127.0.0.1:54321', or 'localhost:8080' vs '127.0.0.1:8080').
Common situations: Tests that dial before the listener goroutine finishes Listen; using the configured address instead of the actual bound address returned by Listen; missing ':' port or hostname aliasing mismatch.
Related errors
- connection error
- already listening on ${addr}
- failed request
- message passed in is nil
- ${rsp.Status}: ${body} (dynamic HTTP status and body)
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/092e4eb703f7a961.
Report an issue: GitHub.