geektutu/7days-golang · error

number of options is more than 1

Error message

number of options is more than 1

What it means

parseOptions() accepts variadic Option pointers and allows at most one; passing more than one returns "number of options is more than 1". It is called by dialTimeout and normalizes the provided option with defaults (MagicNumber, CodecType). This enforces a single-override API design.

Source

Thrown at gee-rpc/day6-load-balance/client.go:203

// and returns its error status.
func (client *Client) Call(ctx context.Context, serviceMethod string, args, reply interface{}) error {
	call := client.Go(serviceMethod, args, reply, make(chan *Call, 1))
	select {
	case <-ctx.Done():
		client.removeCall(call.Seq)
		return errors.New("rpc client: call failed: " + ctx.Err().Error())
	case call := <-call.Done:
		return call.Error
	}
}

func parseOptions(opts ...*Option) (*Option, error) {
	// if opts is nil or pass nil as parameter
	if len(opts) == 0 || opts[0] == nil {
		return DefaultOption, nil
	}
	if len(opts) != 1 {
		return nil, errors.New("number of options is more than 1")
	}
	opt := opts[0]
	opt.MagicNumber = DefaultOption.MagicNumber
	if opt.CodecType == "" {
		opt.CodecType = DefaultOption.CodecType
	}
	return opt, nil
}

func NewClient(conn net.Conn, opt *Option) (*Client, error) {
	f := codec.NewCodecFuncMap[opt.CodecType]
	if f == nil {
		err := fmt.Errorf("invalid codec type %s", opt.CodecType)
		log.Println("rpc client: codec error:", err)
		return nil, err
	}
	// send options with server
	if err := json.NewEncoder(conn).Encode(opt); err != nil {

View on GitHub (pinned to cf36443821)

Solutions

  1. Pass exactly one *Option (or none to use DefaultOption)
  2. Merge multiple configurations into a single Option struct before dialing
  3. If spreading a slice, verify it has at most one element or merge it into one Option first

Example fix

// before
dialTimeout("tcp", addr, baseOpt, overrideOpt) // error

// after
opt := baseOpt // apply overrides onto one struct
if overrideOpt != nil { opt = overrideOpt }
dialTimeout("tcp", addr, opt)
Defensive patterns

Strategy: validation

Validate before calling

if len(opts) > 1 {
    return errors.New("at most one *Option may be passed to dial")
}

Try / catch

opt, err := parseOptions(myOpt)
if err != nil {
    return fmt.Errorf("dial config invalid: %w", err)
}

Prevention

When it happens

Trigger: Calling Dial/DialTimeout/DialHTTP with two or more *Option arguments, e.g. dialTimeout(network, addr, opt1, opt2).

Common situations: Spreading a slice of options into the variadic parameter; merging config layers by passing each option; misunderstanding the variadic signature as accepting multiple configs.

Related errors


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