Quick answer
For the pros: Use ADSI Edit or LDP.exe to set the systemOnly attribute to FALSE on the schema attribute object, or use a script like Set-ADObject with the -Replace parameter. But be careful — changing system-only attributes can break things.
What's happening here?
I know this error is infuriating. You're trying to update an Active Directory attribute — maybe something like badPwdCount or lastLogonTimestamp — and Windows just slaps you with ERROR_DS_CANT_MOD_SYSTEM_ONLY (0x000020B1). This tripped me up the first time too.
The short version: The attribute you're touching has a flag called systemOnly set to TRUE. That flag means "only the system (like the Security Accounts Manager or NTDS) can change this attribute." You, as an admin, can't directly modify it using normal tools like Active Directory Users and Computers. This happens most often with attributes that track security events, replication timestamps, or system-internal data.
Real-world trigger: You're cleaning up old accounts, and you need to reset the badPwdCount before unlocking a user. Or you're running a migration script that tries to write to dSCorePropagationData. Or maybe you're just curious and tried to edit objectVersion on a domain controller. All of these will throw 0x000020B1.
Fix steps (main method)
Step 1: Identify the attribute
First, you need to know exactly which attribute is causing the error. If you're using a script or tool, the error message should name it. If not, run a quick check with LDP.exe or ADSI Edit on the object you're editing. Right-click the object, go to properties, and look for attributes you changed right before the error popped up.
Step 2: Connect to the Schema container
Open ADSI Edit (install it from RSAT if you haven't). Connect to the Schema naming context. You can do this by right-clicking "ADSI Edit" at the top, selecting "Connect to," and then choosing "Schema" in the dropdown.
Step 3: Find the attribute object
Browse to CN=Schema,CN=Configuration,DC=yourdomain,DC=com. Find the attribute you're trying to modify. For example, if the error is on badPwdCount, look for CN=badPwdCount. Double-click it to open properties.
Step 4: Change the systemOnly flag
In the attribute properties, find systemOnly. Change it from TRUE to FALSE. Click OK. This tells Active Directory "hey, it's okay for users to write to this now."
Step 5: Apply your original change
Now go back to your original task — editing the user or computer object. Make the change. It should work. But keep in mind: once you're done, you should change systemOnly back to TRUE to keep things safe.
Alternative fix: Use LDP.exe
If ADSI Edit isn't working (sometimes the schema container hides from you), use LDP.exe:
- Open LDP.exe (from RSAT, or run it from the Windows Tools folder).
- Go to Connection
→Connect and type your domain controller name. - Then Connection
→ Bind with your admin credentials. - Go to View
→ Tree and enter the Schema DN:CN=Schema,CN=Configuration,DC=yourdomain,DC=com. - Find the attribute, right-click, choose Modify.
- In the attribute field, type
systemOnly. In the values field, typeFALSE. Set operation to Replace. Click Enter, then Run.
Alternative fix: PowerShell
If you prefer scripting (and you should), here's a one-liner for PowerShell:
Set-ADObject -Identity "CN=badPwdCount,CN=Schema,CN=Configuration,DC=yourdomain,DC=com" -Replace @{systemOnly=$false}
Replace badPwdCount with your attribute's name and yourdomain.com with actual domain. Run this as Domain Admin from a domain-joined machine with RSAT installed.
Prevention tip
Don't keep systemOnly set to FALSE longer than you need to. Once your change is done, flip it back to TRUE. System-only attributes exist for a reason — they protect internal AD processes. If you leave them writable, a bad script or an attacker could corrupt replication, break password policies, or mess up logon tracking. Also, test this in a lab first. I've seen admins accidentally lock themselves out of the schema by making too many changes at once.
If you're doing this regularly (like in a migration tool), consider using a dedicated service account with permissions only on the specific attributes you need to modify. Use Set-ADObject with -Replace to target just those attributes, not the whole object.