{"record":{"id":"092e4eb703f7a961","repo":"micro/go-micro","slug":"could-not-dial-addr","errorCode":null,"errorMessage":"could not dial ${addr}","messagePattern":"could not dial (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/memory.go","lineNumber":188,"sourceCode":"\t\t\t\texit:    c.exit,\n\t\t\t\tssend:   c.ssend,\n\t\t\t\tsrecv:   c.srecv,\n\t\t\t\tlocal:   c.Remote(),\n\t\t\t\tremote:  c.Local(),\n\t\t\t\ttimeout: m.topts.Timeout,\n\t\t\t\tctx:     m.topts.Context,\n\t\t\t})\n\t\t}\n\t}\n}\n\nfunc (m *memoryTransport) Dial(addr string, opts ...DialOption) (Client, error) {\n\tm.RLock()\n\tdefer m.RUnlock()\n\n\tlistener, ok := m.listeners[addr]\n\tif !ok {\n\t\treturn nil, errors.New(\"could not dial \" + addr)\n\t}\n\n\tvar options DialOptions\n\tfor _, o := range opts {\n\t\to(&options)\n\t}\n\n\tcreader, swriter := io.Pipe()\n\tsreader, cwriter := io.Pipe()\n\n\tclient := &memoryClient{\n\t\t&memorySocket{\n\t\t\tserver: false,\n\t\t\tcsend:  gob.NewEncoder(cwriter),\n\t\t\tcrecv:  gob.NewDecoder(creader),\n\t\t\tssend:  gob.NewEncoder(swriter),\n\t\t\tsrecv:  gob.NewDecoder(sreader), exit: make(chan bool),\n\t\t\tlexit:   listener.exit,","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/transport/memory.go#L170-L206","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","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"],"exampleFix":"// before\nserver.Listen(\":0\") // binds random port\nc.Dial(\"localhost:0\") // could not dial localhost:0\n// after\nl, err := server.Listen(\":0\")\naddr := l.Addr() // actual resolved host:port\nc.Dial(addr)","handlingStrategy":"validation","validationCode":"l, err := m.Listen(\":0\")\nif err != nil { return err }\naddr := l.Addr() // use this exact addr for Dial","typeGuard":null,"tryCatchPattern":"c, err := m.Dial(addr)\nif err != nil && strings.HasPrefix(err.Error(), \"could not dial \") {\n\t// re-check listener is up, use listener.Addr()\n}","preventionTips":["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"],"tags":["transport","memory","dial","address"],"backgroundTag":"could-not-dial","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}