{"record":{"id":"af614d5ccf40a35a","repo":"go-kratos/kratos","slug":"register-failed-instance-duplicated","errorCode":null,"errorMessage":"register failed: instance duplicated: ","messagePattern":"register failed: instance duplicated: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"contrib/registry/discovery/discovery_helper.go","lineNumber":16,"sourceCode":"package discovery\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"os\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/go-kratos/kratos/v3/registry\"\n)\n\nvar (\n\tErrDuplication = errors.New(\"register failed: instance duplicated: \")\n\tErrServerError = errors.New(\"server error\")\n)\n\nconst (\n\t// Discovery server resource uri\n\t_registerURL = \"http://%s/discovery/register\"\n\t//_setURL      = \"http://%s/discovery/set\"\n\t_cancelURL = \"http://%s/discovery/cancel\"\n\t_renewURL  = \"http://%s/discovery/renew\"\n\t_pollURL   = \"http://%s/discovery/polls\"\n\n\t// Discovery server error codes\n\t_codeOK          = 0\n\t_codeNotFound    = -404\n\t_codeNotModified = -304\n\t//_SERVER_ERROR = -500\n\n\t// _registerGap is the gap to renew instance registration.","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/go-kratos/kratos/blob/668db92c2c001e9552594ba5a8aede8456af6d7e/contrib/registry/discovery/discovery_helper.go#L1-L34","documentation":"ErrDuplication is defined in contrib/registry/discovery/discovery_helper.go:16 and returned by Discovery.Register (impl_registrar.go:21) when the same Discovery client already has an entry for this AppID in its in-memory registry map; the error is wrapped with the AppID (errors.Wrap(ErrDuplication, ins.AppID)), so the message ends with the duplicated app id. It is a local double-registration guard evaluated before any HTTP call to the discovery server.","triggerScenarios":"Calling d.Register(ctx, &registry.ServiceInstance{...}) twice with the same service name on the same Discovery instance - the second call hits the 'if _, ok := d.registry[ins.AppID]' branch. Also happens when re-registering after a partial failure without calling Deregister or Close on the client first.","commonSituations":"Hot-reload/restart logic that re-runs the registration path on the same long-lived Discovery value; multiple goroutines registering the same app at startup; retry wrapper around Register that re-enters after the first call already succeeded; mixing manual Register with the kratos registrar lifecycle (kratos registers automatically at server start).","solutions":["Register each AppID exactly once per Discovery client; rely on kratos' app lifecycle instead of calling Register manually","If you must re-register, call Deregister (or Close the old client) first so the map entry is cleared","Guard the registration with a sync.Once or a startup flag","Match it with errors.Is(err, discovery.ErrDuplication) since pkg/errors Wrap supports unwrapping"],"exampleFix":"// before\nvar once sync.Once\nfor _, ins := range instances {\n    if err := d.Register(ctx, ins); err != nil { log.Error(err) }\n}\n\n// after\nregister := sync.OnceFunc(func() {\n    if err := d.Register(ctx, svc); err != nil {\n        if errors.Is(err, discovery.ErrDuplication) { return }\n        log.Error(err)\n    }\n})","handlingStrategy":"try-catch","validationCode":"// guard before registering: ensure one registration per app id per client\nif d == nil || svc.Name == \"\" { return errors.New(\"invalid registration\") }\n// rely on kratos lifecycle; if registering manually, wrap in sync.Once","typeGuard":null,"tryCatchPattern":"if err := d.Register(ctx, svc); err != nil {\n    if errors.Is(err, discovery.ErrDuplication) {\n        // already registered on this client: benign for idempotent startup paths\n        err = nil\n    }\n    return err\n}","preventionTips":["Register each AppID once per Discovery client; let kratos' app lifecycle own registration","Call Deregister or Close before any intentional re-registration","Watch logs for the wrapped AppID in the message to identify which service double-registered"],"tags":["registry","discovery","bilibili","double-registration"],"backgroundTag":null,"analyzedSha":"668db92c2c001e9552594ba5a8aede8456af6d7e","analyzedAt":"2026-08-16T02:07:20.704Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}