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

Identical to error 80 but in day6-load-balance: XDial splits rpcAddr on '@' and requires exactly two parts; anything else is rejected with this message. The unified protocol@addr format lets one dial function dispatch to http or default (tcp) transports.

Source

Thrown at gee-rpc/day6-load-balance/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. Format the address as protocol@addr with a single '@', e.g. 'http@10.0.0.1:7001'.
  2. Prepend 'tcp@' (or the appropriate protocol) when the registry returns bare addresses.
  3. Call Dial/DialHTTP directly if you already know the transport and don't need XDial parsing.

Example fix

// before
XDial(registryAddr) // e.g. "http://localhost:9999/_geerpc_"
// after
XDial("http@localhost: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) { /* normalize to protocol@addr before XDial */ }

Try / catch

c, err := geerpc.XDial(rpcAddr)
if err != nil {
    if strings.Contains(err.Error(), "wrong format") {
        return nil, fmt.Errorf("rpcAddr %q must be protocol@addr", rpcAddr)
    }
    return nil, err
}

Prevention

When it happens

Trigger: XDial called with '10.0.0.1:9999' (no '@'), 'http@10.0.0.1:7001@x' (two '@'), or an empty string.

Common situations: Hardcoded addresses copied from Dial usage; service-registry entries lacking the protocol prefix; string formatting bugs injecting extra '@' characters.

Related errors


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