goharbor/harbor · warning · ErrDuplicateLDAPGroup

a LDAP user group with same DN already exist

Error message

a LDAP user group with same DN already exist

What it means

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.

Source

Thrown at src/core/auth/authenticator.go:44

	libErrors "github.com/goharbor/harbor/src/lib/errors"
	"github.com/goharbor/harbor/src/lib/log"
	"github.com/goharbor/harbor/src/pkg/user"
	"github.com/goharbor/harbor/src/pkg/usergroup/model"
)

// 1.5 seconds
const frozenTime time.Duration = 1500 * time.Millisecond

var lock = NewUserLock(frozenTime)

// ErrorUserNotExist ...
var ErrorUserNotExist = errors.New("user does not exist")

// ErrorGroupNotExist ...
var ErrorGroupNotExist = errors.New("group does not exist")

// ErrDuplicateLDAPGroup ...
var ErrDuplicateLDAPGroup = errors.New("a LDAP user group with same DN already exist")

// ErrInvalidLDAPGroupDN ...
var ErrInvalidLDAPGroupDN = errors.New("the LDAP group DN is invalid")

// ErrNotSupported ...
var ErrNotSupported = errors.New("not supported")

// ErrAuth is the type of error to indicate a failed authentication due to user's error.
type ErrAuth struct {
	details string
}

// Error ...
func (ea ErrAuth) Error() string {
	return fmt.Sprintf("Failed to authenticate user, due to error '%s'", ea.details)
}

// NewErrAuth ...

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. List existing groups (GET /api/v2.0/usergroups) and update the existing one instead of creating a new one
  2. If the old entry is stale (group gone from the directory), delete it first
  3. Give the new group its correct, distinct DN

Example fix

// before: creating a group with a DN that already exists
$ curl -u admin:Pass -X POST https://harbor.example.com/api/v2.0/usergroups \
    -H 'Content-Type: application/json' \
    -d '{"group_name":"devs","group_type":1,"ldap_group_dn":"cn=devs,ou=groups,dc=example,dc=com"}'

// after: reuse the existing group (lookup then PUT)
$ curl -u admin:Pass 'https://harbor.example.com/api/v2.0/usergroups?groupname=devs'
$ curl -u admin:Pass -X PUT https://harbor.example.com/api/v2.0/usergroups/7 \
    -d '{"group_name":"devs","group_type":1,"ldap_group_dn":"cn=dev-team,ou=groups,dc=example,dc=com"}'
Defensive patterns

Strategy: try-catch

Validate before calling

// Before creating, ensure no group owns the DN yet
groups, _, _ := client.UsergroupsApi.ListUserGroups(ctx).Execute()
for _, g := range groups {
    if g.LdapGroupDn != nil && *g.LdapGroupDn == dn { return errors.New("DN already in use") }
}

Type guard

func isDuplicateLDAPGroup(err error) bool { return errors.Is(err, auth.ErrDuplicateLDAPGroup) }

Try / catch

err := ldap.CreateUserGroup(...)
if errors.Is(err, auth.ErrDuplicateLDAPGroup) {
    // switch to updating the existing group instead of failing
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of goharbor/harbor@7b2fd08cc5 (2026-08-16). Data as JSON: /api/errors/0b1e23465cbe0101. Report an issue: GitHub.