{"record":{"id":"b65fc8a5acb02e0e","repo":"geektutu/7days-golang","slug":"number-of-options-is-more-than-1-b65fc8","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/day5-http-debug/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/day5-http-debug/client.go#L185-L221","documentation":"parseOptions (day5-http-debug) enforces that the variadic options argument to the dial functions contains at most one *Option. Passing more than one makes the intent ambiguous, so dialing fails with this error. Passing none (or nil) selects DefaultOption, with MagicNumber forced and empty CodecType defaulted.","triggerScenarios":"Dial/DialTimeout/XDialer invoked with two or more *Option arguments, e.g. dialTimeout(network, addr, defaultOpt, customOpt).","commonSituations":"Refactoring where option fields were split into multiple structs but both are still forwarded; helper wrappers that append their own option on top of the caller's; test code passing both a base and an override option.","solutions":["Supply exactly one *Option (or none for defaults) to the dial function","Fold all desired settings into a single Option instance before dialing","Fix wrapper functions to merge rather than append extra options into the variadic call"],"exampleFix":"// before\nbase := geerpc.DefaultOption\ncustom := &geerpc.Option{CodecType: \"json\"}\nconn, err := geerpc.XDialTimeout(\"tcp\", addr, base, custom)\n\n// after\ncustom := &geerpc.Option{CodecType: \"json\"}\nconn, err := geerpc.XDialTimeout(\"tcp\", addr, custom)","handlingStrategy":"validation","validationCode":"if len(opts) > 1 {\n\treturn fmt.Errorf(\"dial accepts at most one option, got %d\", len(opts))\n}","typeGuard":null,"tryCatchPattern":"conn, err := geerpc.Dial(\"tcp\", addr, opt)\nif err != nil && strings.Contains(err.Error(), \"number of options is more than 1\") {\n\t// merge options into one and redial\n}","preventionTips":["Centralize option construction in one helper returning a single *Option","Audit variadic-forwarding wrappers for accidental extra options","Default to calling dial with no options when defaults suffice"],"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"}