goharbor/harbor · error

empty password

Error message

empty password

What it means

Sentinel error returned by the LDAP controller's Ping (backing POST /api/v2.0/ldap/ping) when no search password is available: the request carried no password and the stored ldap_search_password resolves to empty, or the current auth mode is not db_auth… specifically not LDAP, so there is no stored password to reuse. ldap_search_password is write-only, so GET configurations returning empty never proves it is set.

Source

Thrown at src/pkg/ldap/ldap.go:39

	"net"
	"net/url"
	"strings"
	"time"

	goldap "github.com/go-ldap/ldap/v3"

	"github.com/goharbor/harbor/src/lib/config/models"
	"github.com/goharbor/harbor/src/lib/log"
	"github.com/goharbor/harbor/src/pkg/ldap/model"
)

const pageSize = 1000

// ErrNotFound ...
var ErrNotFound = errors.New("entity not found")

// ErrEmptyPassword ...
var ErrEmptyPassword = errors.New("empty password")

// ErrInvalidCredential ...
var ErrInvalidCredential = errors.New("invalid credential")

// ErrLDAPServerTimeout ...
var ErrLDAPServerTimeout = errors.New("ldap server network timeout")

// ErrLDAPPingFail ...
var ErrLDAPPingFail = errors.New("fail to ping LDAP server")

// ErrDNSyntax ...
var ErrDNSyntax = errors.New("invalid DN syntax")

// ErrInvalidFilter ...
var ErrInvalidFilter = errors.New("invalid filter syntax")

// ErrEmptyBaseDN ...
var ErrEmptyBaseDN = errors.New("empty base dn")

View on GitHub (pinned to 7b2fd08cc5)

Solutions

  1. Send the search password in the ping request body so no stored secret is needed.
  2. Or save it first: PUT /api/v2.0/configurations with ldap_search_password, then ping without it.
  3. Switch auth_mode to ldap_auth before pinging if you expect to reuse the stored secret.

Example fix

# before
curl -X POST https://harbor/api/v2.0/ldap/ping -d '{"url": "ldaps://ad.example.com:636"}'
# after
curl -X POST https://harbor/api/v2.0/ldap/ping -d '{"url": "ldaps://ad.example.com:636", "search_dn": "cn=svc-harbor,ou=svc,dc=example,dc=com", "search_password": "<secret>"}'
Defensive patterns

Strategy: validation

Validate before calling

// Before POST /api/v2.0/ldap/ping with no password:
// ensure a stored secret exists AND auth mode is ldap, else include the password in the request
if req.searchPassword == "" {
    if authMode != "ldap_auth" || !ldapSearchPasswordIsConfigured {
        fail("include search_password in the ping request")
    }
}

Type guard

func isLdapEmptyPassword(err error) bool { return errors.Is(err, ldap.ErrEmptyPassword) }

Try / catch

After calling ping, if errors.Is(err, ldap.ErrEmptyPassword) → prompt for the bind password or save ldap_search_password first, then retry the ping with credentials inline.

Prevention

When it happens

Trigger: POST /api/v2.0/ldap/ping with an empty/omitted password while (a) ldap_search_password was never saved, or (b) auth_mode is db_auth/oidc/uaa so no LDAP secret exists; internally via controller.Ping → defaultPassword.

Common situations: Fresh Harbor installs testing LDAP before saving the bind password; deployments where the password was configured via harbor.yml LDAP_PASSWORD but env-based migration dropped it; testing LDAP while auth mode is still db_auth.

Related errors


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