{"record":{"id":"419362834814e262","repo":"micro/go-micro","slug":"rpc-handle-type-name-is-not-exported","errorCode":null,"errorMessage":"rpc.Handle: type ${name} is not exported","messagePattern":"rpc\\.Handle: type (.+?) is not exported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/rpc_router.go","lineNumber":465,"sourceCode":"\nfunc (router *router) NewHandler(h interface{}, opts ...HandlerOption) Handler {\n\treturn NewRpcHandler(h, opts...)\n}\n\nfunc (router *router) Handle(h Handler) error {\n\trouter.mu.Lock()\n\tdefer router.mu.Unlock()\n\n\tif router.serviceMap == nil {\n\t\trouter.serviceMap = make(map[string]*service)\n\t}\n\n\tif len(h.Name()) == 0 {\n\t\treturn errors.New(\"rpc.Handle: handler has no name\")\n\t}\n\n\tif !isExported(h.Name()) {\n\t\treturn errors.New(\"rpc.Handle: type \" + h.Name() + \" is not exported\")\n\t}\n\n\trcvr := h.Handler()\n\ts := new(service)\n\ts.typ = reflect.TypeOf(rcvr)\n\ts.rcvr = reflect.ValueOf(rcvr)\n\n\t// check name\n\tif _, present := router.serviceMap[h.Name()]; present {\n\t\treturn errors.New(\"rpc.Handle: service already defined: \" + h.Name())\n\t}\n\n\ts.name = h.Name()\n\ts.method = make(map[string]*methodType)\n\n\t// Install the methods\n\tfor m := 0; m < s.typ.NumMethod(); m++ {\n\t\tmethod := s.typ.Method(m)","sourceCodeStart":447,"sourceCodeEnd":483,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/server/rpc_router.go#L447-L483","documentation":"Handle was called with a handler whose Name() is non-empty but not exported (does not start with an uppercase letter). The router only registers exported names so they can be addressed by external clients; unexported names are rejected at registration time.","triggerScenarios":"Registering a handler named e.g. \"calculator\" or \"_internal\"; generating service names from Go type names of unexported types.","commonSituations":"Auto-deriving the service name from an unexported Go struct type; lowercase name strings in config files; renaming a service to a lowercase identifier during refactoring.","solutions":["Change the handler name to start with an uppercase letter (e.g. \"Calculator\")","If the name comes from config, update it to an exported-style identifier","When deriving names from Go types, use an exported type or map to an explicit exported name"],"exampleFix":"// before\nrouter.NewHandler(NewCalcService(\"calculator\"))\n// after\nrouter.NewHandler(NewCalcService(\"Calculator\"))","handlingStrategy":"validation","validationCode":"name := h.Name()\nif name == \"\" || !unicode.IsUpper(rune(name[0])) {\n\treturn fmt.Errorf(\"service name %q must be exported (start with uppercase)\", name)\n}\nrouter.NewHandler(h)","typeGuard":null,"tryCatchPattern":"if err := router.NewHandler(h); err != nil {\n\tif strings.Contains(err.Error(), \"is not exported\") {\n\t\treturn fmt.Errorf(\"fix service name for %T: %w\", h, err)\n\t}\n\treturn err\n}","preventionTips":["Use PascalCase identifiers for all service names","Never derive service names directly from unexported Go types without renaming","Add a startup check that all registered service names begin with an uppercase letter"],"tags":["rpc","registration","naming"],"backgroundTag":"rpc-handler-registration-failed","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}