{"record":{"id":"0b1e23465cbe0101","repo":"goharbor/harbor","slug":"a-ldap-user-group-with-same-dn-already-exist","errorCode":null,"errorMessage":"a LDAP user group with same DN already exist","messagePattern":"a LDAP user group with same DN already exist","errorType":"exception","errorClass":"ErrDuplicateLDAPGroup","httpStatus":null,"severity":"warning","filePath":"src/core/auth/authenticator.go","lineNumber":44,"sourceCode":"\tlibErrors \"github.com/goharbor/harbor/src/lib/errors\"\n\t\"github.com/goharbor/harbor/src/lib/log\"\n\t\"github.com/goharbor/harbor/src/pkg/user\"\n\t\"github.com/goharbor/harbor/src/pkg/usergroup/model\"\n)\n\n// 1.5 seconds\nconst frozenTime time.Duration = 1500 * time.Millisecond\n\nvar lock = NewUserLock(frozenTime)\n\n// ErrorUserNotExist ...\nvar ErrorUserNotExist = errors.New(\"user does not exist\")\n\n// ErrorGroupNotExist ...\nvar ErrorGroupNotExist = errors.New(\"group does not exist\")\n\n// ErrDuplicateLDAPGroup ...\nvar ErrDuplicateLDAPGroup = errors.New(\"a LDAP user group with same DN already exist\")\n\n// ErrInvalidLDAPGroupDN ...\nvar ErrInvalidLDAPGroupDN = errors.New(\"the LDAP group DN is invalid\")\n\n// ErrNotSupported ...\nvar ErrNotSupported = errors.New(\"not supported\")\n\n// ErrAuth is the type of error to indicate a failed authentication due to user's error.\ntype ErrAuth struct {\n\tdetails string\n}\n\n// Error ...\nfunc (ea ErrAuth) Error() string {\n\treturn fmt.Sprintf(\"Failed to authenticate user, due to error '%s'\", ea.details)\n}\n\n// NewErrAuth ...","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/goharbor/harbor/blob/7b2fd08cc568955cca339afeefab27372840d936/src/core/auth/authenticator.go#L26-L62","documentation":"Sentinel ErrDuplicateLDAPGroup is returned by the LDAP auth helper (src/core/auth/ldap/ldap.go:319) when creating or updating a user group whose DN is already owned by another LDAP user group in Harbor's database. DNs must be unique per group.","triggerScenarios":"POST /api/v2.0/usergroups with a DN that already exists on another group; PUT /api/v2.0/usergroups/{id} changing a group's DN to one already in use.","commonSituations":"Recreating a group that still exists in Harbor after it was renamed in the directory duplicate entries left behind by LDAP migrations or manual inserts.","solutions":["List existing groups (GET /api/v2.0/usergroups) and update the existing one instead of creating a new one","If the old entry is stale (group gone from the directory), delete it first","Give the new group its correct, distinct DN"],"exampleFix":"// before: creating a group with a DN that already exists\n$ curl -u admin:Pass -X POST https://harbor.example.com/api/v2.0/usergroups \\\n    -H 'Content-Type: application/json' \\\n    -d '{\"group_name\":\"devs\",\"group_type\":1,\"ldap_group_dn\":\"cn=devs,ou=groups,dc=example,dc=com\"}'\n\n// after: reuse the existing group (lookup then PUT)\n$ curl -u admin:Pass 'https://harbor.example.com/api/v2.0/usergroups?groupname=devs'\n$ curl -u admin:Pass -X PUT https://harbor.example.com/api/v2.0/usergroups/7 \\\n    -d '{\"group_name\":\"devs\",\"group_type\":1,\"ldap_group_dn\":\"cn=dev-team,ou=groups,dc=example,dc=com\"}'","handlingStrategy":"try-catch","validationCode":"// Before creating, ensure no group owns the DN yet\ngroups, _, _ := client.UsergroupsApi.ListUserGroups(ctx).Execute()\nfor _, g := range groups {\n    if g.LdapGroupDn != nil && *g.LdapGroupDn == dn { return errors.New(\"DN already in use\") }\n}","typeGuard":"func isDuplicateLDAPGroup(err error) bool { return errors.Is(err, auth.ErrDuplicateLDAPGroup) }","tryCatchPattern":"err := ldap.CreateUserGroup(...)\nif errors.Is(err, auth.ErrDuplicateLDAPGroup) {\n    // switch to updating the existing group instead of failing\n}","preventionTips":["Make create-or-update idempotent keyed on DN","Clean stale user groups after directory renames"],"tags":["harbor","ldap","usergroup","duplicate"],"backgroundTag":null,"analyzedSha":"7b2fd08cc568955cca339afeefab27372840d936","analyzedAt":"2026-08-16T00:00:10.961Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}