{"record":{"id":"aae33583e6b534d5","repo":"geektutu/7days-golang","slug":"invalid-codec-type-s-aae335","errorCode":null,"errorMessage":"invalid codec type %s","messagePattern":"invalid codec type (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day4-timeout/client.go","lineNumber":213,"sourceCode":"\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 {\n\t\tlog.Println(\"rpc client: options error: \", err)\n\t\treturn\n\t}\n\treturn newClientCodec(f(conn), opt), nil\n}\n\nfunc newClientCodec(cc codec.Codec, opt *Option) *Client {\n\tclient := &Client{\n\t\tseq:     1, // seq starts with 1, 0 means invalid call\n\t\tcc:      cc,\n\t\topt:     opt,\n\t\tpending: make(map[uint64]*Call),\n\t}","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day4-timeout/client.go#L195-L231","documentation":"day4-timeout's NewClient (named-return form) fails when opt.CodecType has no constructor in codec.NewCodecFuncMap and returns \"invalid codec type %s\" before any data is sent. The timeout variant otherwise behaves like the earlier NewClient.","triggerScenarios":"Calling NewClient/Dial with an Option carrying an unregistered CodecType string; only empty strings get defaulted to Gob in parseOptions.","commonSituations":"Mixing option structs across day branches; hardcoding \"gob\"/\"json\" instead of codec constants; custom codec registered on server but not client binary.","solutions":["Set CodecType to codec.GobType or leave it empty","Register the custom codec on the client before Dial","Use DefaultOption / pass nil options","Verify the constant values with fmt.Printf(\"%q\") to catch invisible typos"],"exampleFix":"// before\nopt := &geerpc.Option{CodecType: \"gob\"}\n// after\nopt := &geerpc.Option{CodecType: codec.GobType} // \"application/gob\"","handlingStrategy":"validation","validationCode":"if _, ok := codec.NewCodecFuncMap[opt.CodecType]; opt.CodecType != \"\" && !ok {\n\treturn fmt.Errorf(\"codec %q unsupported\", opt.CodecType)\n}\nclient, err := geerpc.Dial(\"tcp\", addr, opt)","typeGuard":"func codecSupported(t string) bool {\n\t_, ok := codec.NewCodecFuncMap[t]\n\treturn ok\n}","tryCatchPattern":"client, err := geerpc.Dial(\"tcp\", addr, opt)\nif err != nil && strings.Contains(err.Error(), \"invalid codec type\") {\n\topt.CodecType = codec.GobType\n\tclient, err = geerpc.Dial(\"tcp\", addr, opt)\n}","preventionTips":["Use codec.GobType or empty string only","Register any custom codec before Dial in an init() function","Centralize Option construction in one helper shared by all clients","Add a startup assertion that the needed codec is registered"],"tags":["rpc","configuration","codec"],"backgroundTag":"invalid-codec-type","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"}