| Tested on | Rocky Linux 10.2 (Red Quartz) |
|---|---|
| Package | 389-ds-base 3.2.0-8.el10_2 |
| Applies to | RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora |
| Privilege | sudo or root |
| Scope | Fix LDAP error 50: ACIs, group membership, deny rules, effective rights, and access logs. Does not cover unrelated LDAP error codes. |
| Related guides | Install 389 Directory Server ACI examples Get Effective Rights dsconf commands Fix LDAP invalid credentials error 49 |
LDAP result code 50 means the authorization identity used for the operation does not have sufficient access rights. In this lab, the user bind succeeds and 389 Directory Server rejects the later modify during ACI evaluation. Anonymous operations can also return error 50 when anonymous access is not permitted.
Clients usually print:
ldap_modify: Insufficient access (50)The same code appears on add, delete, modify DN, and some extended operations:
ldap_add: Insufficient access (50)ldap_delete: Insufficient access (50)389 DS often adds a more specific line naming the missing privilege:
additional info: Insufficient 'write' privilege to the 'telephoneNumber' attribute of entry 'uid=user2,ou=people,dc=example,dc=com'.RFC 4511 defines result code 50 as insufficientAccessRights. It does not require a successful authenticated bind first. Read the diagnostic text alongside the number. The additional info line usually names the attribute, entry, or operation that failed ACI evaluation.
When the bind itself fails with error 49, work through Separate error 49 from error 50 before editing ACIs. When the server returns error 53 with messages such as Password must be changed, Server is read-only, or RootDN access control violation, use fix LDAP unwilling to perform error 53 instead of editing ACIs.
| LDAP operation | Main ACI rights to inspect |
|---|---|
| Modify an attribute | write on the target attribute |
| Add an entry | add on the new entry plus permitted writes to its attributes |
| Delete an entry | delete on the target entry; attribute-value restrictions can also affect deletion |
| Rename an entry | write on the entry and the old or new RDN attributes |
| Move an entry | moddn with matching target_from and target_to, plus required RDN attribute rights |
| Search | search to match attributes and read to return values |
This guide demonstrates attribute write failures. For add, delete, or modify-DN errors, run Get Effective Rights against the same subject and target but inspect the operation-specific entry and attribute rights described in the effective rights chapter.
Use the cause table below to jump to the fix that matches your situation. ACI design, macro rules, self-service policy, and delegated administration stay in the linked chapters.
Examples use instance ldap1 on ldap1.example.com:389 with suffix dc=example,dc=com, users uid=user1 and uid=user2 under ou=people, and delegated group cn=profile-editors,ou=Groups. The lab includes self-service ACIs from self-service password and profile ACIs. Create matching test entries before you follow the modify exercises, or substitute your own lab accounts.
Causes and fixes at a glance
| Symptom or situation | Likely cause | Fix |
|---|---|---|
ldapwhoami fails before any modify |
Authentication problem, not ACI | Separate error 49 from error 50 |
| User cannot change another user's attribute | Self-only ACI (ldap:///self) |
Fix self-service scope |
| Delegated rule exists but modify still fails | groupdn mismatch or missing membership |
Fix groupdn membership |
| Allow rule looks correct but write still denied | Deny rule overrides allow | Fix deny rule precedence |
| Need attribute-level proof before editing ACIs | GER not run or wrong subject DN | Inspect rights with Get Effective Rights |
| Failure only visible in application logs | Access log not checked | Read the access log |
| Broad policy design still unclear | Missing baseline ACI examples | ACI examples and advanced ACI targets |
The access log at /var/log/dirsrv/slapd-INSTANCE/access pairs each operation request with its result on the same conn= and op= numbers. A denied modify pair looks like this:
conn=35 op=1 MOD dn="uid=user2,ou=people,dc=example,dc=com"
conn=35 op=1 RESULT err=50 tag=103 nentries=0Search recent failures with the denied operation request included:
sudo grep -B1 'RESULT err=50' /var/log/dirsrv/slapd-ldap1/access | tail -10The -B1 flag includes the MOD, ADD, DEL, or MODRDN request immediately before each RESULT err=50 line. Use the full connection trace in Read the access log to confirm which identity authenticated before the denied operation.
Separate error 49 from error 50
Confirm the bind identity with the ldapwhoami command before you change ACIs. A password bind that fails authentication never reaches authorization.
ldapwhoami -x -H ldap://ldap1.example.com:389 -D "uid=user1,ou=people,dc=example,dc=com" -y /root/user1.pwSample output:
dn: uid=user1,ou=people,dc=example,dc=comA successful bind prints the entry DN. When this command returns error 49, stop here and follow fix LDAP invalid credentials error 49.
Repeat the failing operation only after ldapwhoami succeeds. Authorization diagnostics assume the bind identity in -D is the identity Directory Server evaluates against ACIs.
Inspect ACIs on the target and parents
ACI inspection uses the ldapsearch command on the target entry and each parent container.
List ACIs on the target entry first:
ldapsearch -LLL -o ldif-wrap=no -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=user2,ou=people,dc=example,dc=com" -s base "(objectClass=*)" aciA user entry often carries no aci values. The next search shows the rules on the parent container:
ldapsearch -LLL -o ldif-wrap=no -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -b "ou=People,dc=example,dc=com" -s base "(objectClass=*)" aciSample output (trimmed):
dn: ou=People,dc=example,dc=com
aci: (targetattr="mail || telephoneNumber || mobile || displayName || preferredLanguage || postalAddress")(version 3.0; acl "Self write profile attributes"; allow (write) userdn="ldap:///self";)Finish on the suffix in case a broader rule applies above the container:
ldapsearch -LLL -o ldif-wrap=no -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -b "dc=example,dc=com" -s base "(objectClass=*)" aciSample output (trimmed):
dn: dc=example,dc=com
aci: (targetattr="dc || description || objectClass")(targetfilter="(objectClass=domain)")(version 3.0; acl "Enable anyone domain read"; allow (read, search, compare)(userdn="ldap:///anyone");)ACIs inherited from parent entries participate in the decision. An allow on ou=People can therefore be blocked by an applicable deny on the suffix. ACI placement determines scope, but applicable rules are evaluated together by their semantics rather than by list order alone.
Fix self-service scope
Self-service ACIs commonly use userdn="ldap:///self". That bind rule matches only when the target entry is the same as the authenticated user. A user who may edit their own telephoneNumber still receives error 50 on another account.
Save a cross-account modify attempt as /tmp/user2-tel.ldif:
dn: uid=user2,ou=people,dc=example,dc=com
changetype: modify
replace: telephoneNumber
telephoneNumber: +1-555-9999Run the modify as user1 with the ldapmodify command:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "uid=user1,ou=people,dc=example,dc=com" -y /root/user1.pw -f /tmp/user2-tel.ldifSample output:
ldap_modify: Insufficient access (50)
additional info: Insufficient 'write' privilege to the 'telephoneNumber' attribute of entry 'uid=user2,ou=people,dc=example,dc=com'.
modifying entry "uid=user2,ou=people,dc=example,dc=com"The bind succeeded; the self-write rule does not apply across accounts.
ldap:///self is correct for profile self-service. It is not a bug when cross-account writes fail.
Verify the same user can still update their own entry. Save /tmp/user1-tel.ldif:
dn: uid=user1,ou=people,dc=example,dc=com
changetype: modify
replace: telephoneNumber
telephoneNumber: +1-555-0202Apply it as user1:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "uid=user1,ou=people,dc=example,dc=com" -y /root/user1.pw -f /tmp/user1-tel.ldifSample output:
modifying entry "uid=user1,ou=people,dc=example,dc=com"When self-modify works but cross-account work fails, add a separate delegated ACI with groupdn or an explicit userdn. See delegated administration for scoped help-desk and operator roles.
Inspect rights with Get Effective Rights
Get Effective Rights (GER) shows how ACIs combine for a subject on a target entry. Run this step while only self-service ACIs apply, before you add delegated or deny rules in the sections below.
Evaluate user1 on user2:
ldapsearch -LLL -o ldif-wrap=no -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=user2,ou=people,dc=example,dc=com" -s base -E '!1.3.6.1.4.1.42.2.27.9.5.2=:dn:uid=user1,ou=people,dc=example,dc=com' "(objectClass=*)" telephoneNumber mailSample output:
dn: uid=user2,ou=people,dc=example,dc=com
telephoneNumber: +1-555-9999
mail: user2@example.com
entryLevelRights: none
attributeLevelRights: telephoneNumber:none, mail:nonetelephoneNumber:none confirms no write, read, search, or compare rights for user1 on user2 under the self-service policy alone.
After a deny rule is in place, GER reports telephoneNumber:none for the subject even when an allow rule exists elsewhere on the same attribute. Pair GER with a live ldapmodify as the subject. Full syntax and interpretation codes are in test ACI permissions with Get Effective Rights.
Fix groupdn membership
Delegated writes often use groupdn="ldap:///cn=GROUP,...". The bind DN must be listed on the group entry, and the groupdn value must identify that same group entry.
Confirm group membership:
ldapsearch -LLL -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -b "cn=profile-editors,ou=Groups,dc=example,dc=com" -s base "(objectClass=*)" memberSample output:
dn: cn=profile-editors,ou=Groups,dc=example,dc=com
member: uid=user1,ou=people,dc=example,dc=comuser1 is a member. An ACI that references cn=ldap-editors instead would not match even when the human-readable group name looks similar.
Add a delegated write rule for profile editors on telephoneNumber. Save /tmp/editors-aci.ldif:
dn: ou=People,dc=example,dc=com
changetype: modify
add: aci
aci: (targetattr="telephoneNumber")(target="ldap:///uid=*,ou=People,dc=example,dc=com")(version 3.0; acl "Editors write telephoneNumber"; allow (write) groupdn="ldap:///cn=profile-editors,ou=Groups,dc=example,dc=com";)Apply as Directory Manager:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -f /tmp/editors-aci.ldifSample output:
modifying entry "ou=People,dc=example,dc=com"Retry the cross-account modify as user1:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "uid=user1,ou=people,dc=example,dc=com" -y /root/user1.pw -f /tmp/user2-tel.ldifSample output:
modifying entry "uid=user2,ou=people,dc=example,dc=com"Confirm the new value as user2:
ldapsearch -LLL -x -H ldap://ldap1.example.com:389 -D "uid=user2,ou=people,dc=example,dc=com" -y /root/user2.pw -b "uid=user2,ou=people,dc=example,dc=com" -s base "(objectClass=*)" telephoneNumberSample output:
dn: uid=user2,ou=people,dc=example,dc=com
telephoneNumber: +1-555-9999When membership is correct but the modify still fails, compare the groupdn with the DN returned by ldapsearch. Confirm the group RDN, parent containers, suffix, and membership attribute rather than relying on the group's display name.
Fix deny rule precedence
389 Directory Server evaluates applicable ACIs by their semantics. A matching deny takes precedence over an allow on the same target, regardless of where each rule is stored.
Add a deny rule on the same attribute. Save /tmp/deny-tel.ldif:
dn: ou=People,dc=example,dc=com
changetype: modify
add: aci
aci: (targetattr="telephoneNumber")(target="ldap:///uid=*,ou=People,dc=example,dc=com")(version 3.0; acl "Deny telephoneNumber writes"; deny (write) userdn="ldap:///anyone";)Apply as Directory Manager:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -f /tmp/deny-tel.ldifSample output:
modifying entry "ou=People,dc=example,dc=com"Retry the delegated modify:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "uid=user1,ou=people,dc=example,dc=com" -y /root/user1.pw -f /tmp/user2-tel.ldifSample output:
ldap_modify: Insufficient access (50)
additional info: Insufficient 'write' privilege to the 'telephoneNumber' attribute of entry 'uid=user2,ou=people,dc=example,dc=com'.Error 50 returns even though the profile-editors allow rule is still present. Remove or narrow the deny rule so it no longer matches the intended exception. When selected identities must retain access, add an exclusion to the deny bind rule rather than adding another allow at a lower or more specific target. Document deny rules beside their matching allows in change tickets so operators do not chase group membership alone.
Remove the demonstration deny rule
The broad deny blocks later lab work until you remove it. Save /tmp/remove-deny-tel.ldif:
dn: ou=People,dc=example,dc=com
changetype: modify
delete: aci
aci: (targetattr="telephoneNumber")(target="ldap:///uid=*,ou=People,dc=example,dc=com")(version 3.0; acl "Deny telephoneNumber writes"; deny (write) userdn="ldap:///anyone";)Apply as Directory Manager:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "cn=Directory Manager" -y /root/dm.pw -f /tmp/remove-deny-tel.ldifSample output:
modifying entry "ou=People,dc=example,dc=com"Retry the delegated modify to confirm the group allow works again:
ldapmodify -x -H ldap://ldap1.example.com:389 -D "uid=user1,ou=people,dc=example,dc=com" -y /root/user1.pw -f /tmp/user2-tel.ldifSample output:
modifying entry "uid=user2,ou=people,dc=example,dc=com"The delegated profile-editors ACI remains in place for later exercises. Delete it separately when you finish the lab.
Read the access log
The access log ties a failed result code to the authenticated DN and operation type. Trigger a failing modify, then search for the denied operation:
sudo grep -B1 'RESULT err=50' /var/log/dirsrv/slapd-ldap1/access | tail -10Sample output (trimmed):
conn=35 op=1 MOD dn="uid=user2,ou=people,dc=example,dc=com"
conn=35 op=1 RESULT err=50 tag=103 nentries=0The line before RESULT err=50 is normally the denied operation request, not the earlier bind result. Inspect the full connection using the conn= value from that pair:
sudo grep 'conn=35 ' /var/log/dirsrv/slapd-ldap1/access | tail -10Sample output (trimmed):
conn=35 op=0 BIND dn="uid=user1,ou=people,dc=example,dc=com" method=128 version=3
conn=35 op=0 RESULT err=0 tag=97 nentries=0 dn="uid=user1,ou=people,dc=example,dc=com"
conn=35 op=1 MOD dn="uid=user2,ou=people,dc=example,dc=com"
conn=35 op=1 RESULT err=50 tag=103 nentries=0op=0 with err=0 and a dn= field is the successful bind. op=1 with err=50 is the denied modify on the same connection. When several clients connect at once, match conn= and op= numbers rather than relying on wall-clock time alone.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Error 49 on ldapwhoami |
Wrong password or bind DN | Separate error 49 from error 50 |
| Error 50 only on one attribute | Missing targetattr or self-only scope |
Add attribute to targetattr; use delegated groupdn for cross-account work |
| Group member but error 50 persists | Wrong groupdn DN or deny rule |
Compare group DN to ACI; remove or narrow deny |
GER shows write but ldapmodify returns 50 |
Wrong GER subject, target, attribute, or endpoint; operation needs additional rights | Repeat GER against the same server and exact target, then inspect the denied operation and applicable parent ACIs |
| Anonymous search works; modify fails | Anonymous read allowed; write requires authenticated allow | Expected behavior — add write ACI for the bind identity |
| Change applied but clients still fail | Editing the wrong instance, suffix, target, or parent entry | Confirm the -H host and port, suffix DN, ACI target, and the entry on which the ACI was stored |
References
- RFC 4511 — LDAP result codes
- 389 Directory Server documentation
- Red Hat Directory Server 13 — Managing access control
- Red Hat Directory Server 13 — Log files reference
Summary
LDAP error 50 in 389 Directory Server means the authorization identity lacks sufficient rights for the requested operation. Confirm authenticated binds with ldapwhoami when error 49 is possible, read the additional info line for the missing attribute or entry right, list ACIs on the target and its parents, use Get Effective Rights to see effective attribute codes, and check the access log for the denied operation and its connection trace. Separate self-service ldap:///self rules from delegated groupdn policy, and remember that a matching deny overrides an allow regardless of rule placement.

