{"record":{"id":"a6a12d6d674216d9","repo":"geektutu/7days-golang","slug":"number-of-options-is-more-than-1-a6a12d","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/day4-timeout/client.go","lineNumber":200,"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 *Client, err 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\n\t}\n\t// send options with server\n\tif err = json.NewEncoder(conn).Encode(opt); err != nil {","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day4-timeout/client.go#L182-L218","documentation":"parseOptions validates the variadic options passed to Dial/DialTimeout (XDialer). The library supports at most one *Option argument; if the caller supplies two or more, it refuses to guess which to use and returns this error. Zero options or a single nil option falls back to DefaultOption.","triggerScenarios":"DialTimeout(\"tcp\", addr, opt1, opt2) or any dial function invoked with more than one *Option value in the variadic opts parameter.","commonSituations":"Migrating code that used to pass (timeout, option) and moving fields into Option incorrectly; calling a wrapper that forwards its own variadic slice plus an explicit option; copy-paste leaving a leftover default option argument.","solutions":["Pass at most one *Option to the dial function","Merge desired settings into a single Option struct (set CodecType, ConnectionTimeout, etc. on one instance)","Review wrapper functions that spread multiple option values into the variadic parameter"],"exampleFix":"// before\nopt1 := &geerpc.Option{CodecType: \"gob\"}\nopt2 := geerpc.DefaultOption\nconn, err := geerpc.DialTimeout(\"tcp\", addr, opt1, opt2)\n\n// after\nopt := &geerpc.Option{CodecType: \"gob\"}\nconn, err := geerpc.DialTimeout(\"tcp\", addr, opt)","handlingStrategy":"validation","validationCode":"// validate options before dialing\nfunc makeOpts(opts ...*geerpc.Option) ([]*geerpc.Option, error) {\n\tif len(opts) > 1 {\n\t\treturn nil, fmt.Errorf(\"expected at most 1 option, got %d\", len(opts))\n\t}\n\treturn opts, nil\n}","typeGuard":null,"tryCatchPattern":"conn, err := geerpc.DialTimeout(\"tcp\", addr, opt)\nif err != nil {\n\tif strings.Contains(err.Error(), \"number of options is more than 1\") {\n\t\t// fix call site: pass a single merged option\n\t}\n}","preventionTips":["Never pass more than one *Option to dial functions","Build one options struct per dial site, possibly via a small config aggregator","Add a lint/test asserting wrapper functions forward a single option"],"tags":["rpc","options","api-misuse","go"],"backgroundTag":"too-many-arguments","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"}