{"record":{"id":"57ac6f2e26eadfb0","repo":"geektutu/7days-golang","slug":"number-of-options-is-more-than-1-57ac6f","errorCode":null,"errorMessage":"number of options is more than 1","messagePattern":"number of options is more than 1","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day7-registry/client.go","lineNumber":203,"sourceCode":"// and returns its error status.\nfunc (client *Client) Call(ctx context.Context, serviceMethod string, args, reply interface{}) error {\n\tcall := client.Go(serviceMethod, args, reply, make(chan *Call, 1))\n\tselect {\n\tcase <-ctx.Done():\n\t\tclient.removeCall(call.Seq)\n\t\treturn errors.New(\"rpc client: call failed: \" + ctx.Err().Error())\n\tcase call := <-call.Done:\n\t\treturn call.Error\n\t}\n}\n\nfunc parseOptions(opts ...*Option) (*Option, error) {\n\t// if opts is nil or pass nil as parameter\n\tif len(opts) == 0 || opts[0] == nil {\n\t\treturn DefaultOption, nil\n\t}\n\tif len(opts) != 1 {\n\t\treturn nil, errors.New(\"number of options is more than 1\")\n\t}\n\topt := opts[0]\n\topt.MagicNumber = DefaultOption.MagicNumber\n\tif opt.CodecType == \"\" {\n\t\topt.CodecType = DefaultOption.CodecType\n\t}\n\treturn opt, nil\n}\n\nfunc NewClient(conn net.Conn, opt *Option) (*Client, error) {\n\tf := codec.NewCodecFuncMap[opt.CodecType]\n\tif f == nil {\n\t\terr := fmt.Errorf(\"invalid codec type %s\", opt.CodecType)\n\t\tlog.Println(\"rpc client: codec error:\", err)\n\t\treturn nil, err\n\t}\n\t// send options with server\n\tif err := json.NewEncoder(conn).Encode(opt); err != nil {","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day7-registry/client.go#L185-L221","documentation":"parseOptions validates that at most one *Option is supplied to NewClient/XDial. Passing more than one option argument is rejected because a single Option struct fully configures the client; the library cannot merge multiple option sets.","triggerScenarios":"Calling geeRPC.NewClient(conn, opt1, opt2) or geeRPC.XDial(addr, opt1, opt2) with two or more variadic option arguments.","commonSituations":"Migrating from functional-options style APIs (WithCodec(...), WithTimeout(...)) and passing each as a separate argument, copy-pasted dial code appending an extra option, or wrapper functions forwarding both a default and a user option.","solutions":["Merge settings into a single &Option{CodecType: ..., ConnectionTimeout: ...} struct and pass only it.","Pass no option to use DefaultOption, or a single custom one.","If wrapping, combine defaults with user overrides in one Option value before dialing."],"exampleFix":"// before\nclient, err := geeRPC.XDial(addr, opt, anotherOpt) // errors\n// after\nmerged := &geeRPC.Option{CodecType: opt.CodecType, ConnectionTimeout: anotherOpt.ConnectionTimeout}\nclient, err := geeRPC.XDial(addr, merged)","handlingStrategy":"validation","validationCode":"func buildOption(opts ...*geeRPC.Option) (*geeRPC.Option, error) {\n    if len(opts) > 1 { return nil, errors.New(\"at most one Option allowed\") }\n    return opts[0], nil // or nil for DefaultOption\n}","typeGuard":null,"tryCatchPattern":"if err != nil && err.Error() == \"number of options is more than 1\" { return fmt.Errorf(\"merge options into a single geeRPC.Option: %w\", err) }","preventionTips":["Merge all settings into one Option struct before dialing.","Do not pass functional-style option values as separate variadic args.","Prefer passing nil (DefaultOption) and mutate a copy only when needed."],"tags":["rpc","configuration","invalid-argument","client"],"backgroundTag":"too-many-options-argument","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}