geektutu/7days-golang · error

rpc client err: wrong format '%s', expect protocol@addr

Error message

rpc client err: wrong format '%s', expect protocol@addr

What it means

XDial parses a unified rpcAddr string of the form protocol@addr and returns an error when the string does not split into exactly two '@'-separated parts. The library uses this format to support multiple transports (http, tcp, unix) behind a single dial entry point. A malformed address cannot be routed to any transport, so dialing is refused immediately.

Source

Thrown at gee-rpc/day5-http-debug/client.go:313

		err = errors.New("unexpected HTTP response: " + resp.Status)
	}
	return nil, err
}

// DialHTTP connects to an HTTP RPC server at the specified network address
// listening on the default HTTP RPC path.
func DialHTTP(network, address string, opts ...*Option) (*Client, error) {
	return dialTimeout(NewHTTPClient, network, address, opts...)
}

// XDial calls different functions to connect to a RPC server
// according the first parameter rpcAddr.
// rpcAddr is a general format (protocol@addr) to represent a rpc server
// eg, http@10.0.0.1:7001, tcp@10.0.0.1:9999, unix@/tmp/geerpc.sock
func XDial(rpcAddr string, opts ...*Option) (*Client, error) {
	parts := strings.Split(rpcAddr, "@")
	if len(parts) != 2 {
		return nil, fmt.Errorf("rpc client err: wrong format '%s', expect protocol@addr", rpcAddr)
	}
	protocol, addr := parts[0], parts[1]
	switch protocol {
	case "http":
		return DialHTTP("tcp", addr, opts...)
	default:
		// tcp, unix or other transport protocol
		return Dial(protocol, addr, opts...)
	}
}

View on GitHub (pinned to cf36443821)

Solutions

  1. Ensure rpcAddr contains exactly one '@' separating protocol from address, e.g. 'tcp@10.0.0.1:9999'.
  2. If the address lacks a protocol prefix, prepend the desired one ('http@', 'tcp@', or 'unix@') before calling XDial.
  3. For plain addresses, call Dial('tcp', addr) directly instead of XDial.

Example fix

// before
client, err := geerpc.XDial("10.0.0.1:9999")
// after
client, err := geerpc.XDial("tcp@10.0.0.1:9999")
Defensive patterns

Strategy: validation

Validate before calling

func validRPCAddr(addr string) bool {
    parts := strings.Split(addr, "@")
    return len(parts) == 2 && parts[0] != "" && parts[1] != ""
}
if !validRPCAddr(rpcAddr) { /* fix or reject before calling XDial */ }

Try / catch

c, err := geerpc.XDial(rpcAddr)
if err != nil {
    if strings.Contains(err.Error(), "wrong format") {
        // fall back to a default protocol prefix
        c, err = geerpc.XDial("tcp@" + rpcAddr)
    }
    if err != nil { log.Fatal(err) }
}

Prevention

When it happens

Trigger: Calling XDial with a rpcAddr that contains no '@' (e.g. '10.0.0.1:9999') or more than one '@' (e.g. 'http@10.0.0.1:7001@extra').

Common situations: Config files storing bare host:port addresses instead of protocol@addr; users forgetting the protocol prefix; template/env var interpolation inserting an extra '@' (e.g. credentials in a URL).

Related errors


AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03). Data as JSON: /api/errors/6e6e3c87d952279b. Report an issue: GitHub.