micro/go-micro · warning

%s-%s | %s

Error message

%s-%s | %s

What it means

ServeConn's receive loop sets a global error when sock.Recv fails, wrapping it with the server name, ID, and the remote peer address in the format "<name>-<id> | <remote>: <cause>". Because a Recv failure means the socket is no longer usable, the loop returns immediately and the connection is torn down.

Source

Thrown at server/rpc_server.go:154

		}
	}()

	for {
		msg := transport.Message{
			Header: make(map[string]string),
		}

		// Close connection if Connection: close header was set
		if closeConn {
			return
		}

		// Process inbound messages one at a time
		if err := sock.Recv(&msg); err != nil {
			// Set a global error and return.
			// We're saying we essentially can't
			// use the socket anymore
			gerr = errors.Wrapf(err, "%s-%s | %s", s.opts.Name, s.opts.Id, sock.Remote())

			return
		}

		// Keep track of when to close the connection
		if c := msg.Header["Connection"]; c == "close" {
			closeConn = true
		}

		// Check the message header for micro message header, if so handle
		// as micro event
		if t := msg.Header[headers.Message]; len(t) > 0 {
			// Process the event
			ev := newEvent(msg)

			if err := s.HandleEvent(ev.Topic())(ev); err != nil {
				msg.Header[headers.Error] = err.Error()
				logger.Logf(log.ErrorLevel, "failed to handle event: %v", err)

View on GitHub (pinned to 24529f1404)

Solutions

  1. Check the wrapped cause (errors.Cause) — ErrConnClosed / io.EOF are normal disconnects
  2. Treat these as client-side lifecycle events and log at debug rather than error for normal closes
  3. Investigate client idle/keepalive settings if disconnects are frequent
  4. Ensure the transport has adequate timeouts for long-running requests
  5. Verify load balancers/proxies aren't terminating idle connections

Example fix

// before
// server logs noisy errors on every normal client disconnect
log.Errorf("%v", gerr)
// after
cause := errors.Cause(err)
if errors.Is(cause, io.EOF) || errors.Is(cause, transport.ErrConnClosed) {
    log.Debugf("client %s disconnected", sock.Remote())
} else {
    log.Errorf("%v", gerr)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// client side: keepalive so the server doesn't see unexpected dead peers
sock.SetTimeout(10 * time.Second)
// send a close header when done
msg.Header["Connection"] = "close"

Try / catch

if err := server.Start(); err != nil { ... }
// server-side: wrap the ServeConn error and classify
gerr := errors.Wrapf(err, "%s-%s | %s", name, id, remote)
if errors.Is(errors.Cause(err), io.EOF) || errors.Is(errors.Cause(err), transport.ErrConnClosed) {
    log.Debugf("peer %s disconnected", remote)
} else {
    log.Errorf("%v", gerr)
}

Prevention

When it happens

Trigger: Any failure receiving from the client socket during message processing: the client disconnected/closed the connection, network timeout, socket closed by shutdown, or a transport-level error (e.g. connection reset by peer).

Common situations: Client crash or abrupt disconnect mid-request; client idle timeouts; load balancer killing long-lived connections; server shutdown closing sockets; network partitions between client and server.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/742169c83601c95a. Report an issue: GitHub.