chage Error: 'chage: cannot change to shadow password aging information' — Cause, Fix, and Troubleshooting Guide
Fix chage 'cannot change to shadow password aging information': missing shadow entry, LDAP/SSSD accounts, or a locked shadow database. Diagnose and fix.
- #security
- #hardening
- #troubleshooting
- #linux
- #pam
Stuck on this DevOps Security & Hardening error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
What this error means
chage sets password-aging fields (max age, warning, expiry) that live in /etc/shadow. This error means it could not write those fields — the account has no local shadow entry, the account is managed by a network directory rather than local files, or the shadow database is locked/immutable.
chage: cannot change to shadow password aging information for user 'appsvc'
Password aging is a common CIS/STIG hardening requirement, so this shows up while automating expiry policy across a fleet — and the fix depends on where the account actually lives.
How it manifests on the host
sudo chage -M 90 userfails with the message above; nothing in/etc/shadowchanges.chage -l userworks for local users but errors for directory-backed ones.- The failure appears only inside containers or minimal images.
- A hardening playbook applying aging policy fails on a subset of accounts.
System configuration causes
- No local shadow entry. The user exists in
/etc/passwd(or only in a directory) but has no/etc/shadowline to update. - Network-managed account. The user comes from LDAP/AD via SSSD/nss; aging must be set in the directory, not with local
chage. - Shadow file locked. A concurrent
passwd/usermodholds/etc/shadow.lock, or/etcis read-only. - Immutable attribute.
/etc/shadowhas the+i(immutable) bit set by a hardening step. - Corrupt shadow entry with the wrong number of fields.
Interrogating the host
# Does the user have a local shadow entry at all?
sudo getent shadow appsvc # empty => not a local shadow user
getent passwd appsvc # where does the account come from?
# Is the account provided by a network directory?
sudo getent passwd appsvc | cut -d: -f1
systemctl is-active sssd 2>/dev/null
# Is the shadow file locked or immutable?
ls -l /etc/shadow.lock 2>/dev/null
lsattr /etc/shadow 2>/dev/null
mount | grep ' / ' # is / (or /etc) read-only?
If getent shadow returns nothing but getent passwd shows the user, the account is not local — that is the usual cause.
Remediation
1. For a network (LDAP/AD) account, set aging in the directory, not with local chage. Use the directory’s tooling (ldapmodify, AD password policy, or SSSD-configured policy); local chage cannot write there.
2. Create the missing shadow entry for a genuinely local user (e.g. one added with useradd -p oddly or restored from a passwd-only backup):
sudo pwconv # regenerates /etc/shadow from /etc/passwd where missing
sudo chage -M 90 -W 7 appsvc
3. Clear an immutable bit set by a hardening step, apply, then restore protection if desired:
sudo lsattr /etc/shadow
sudo chattr -i /etc/shadow
sudo chage -M 90 appsvc
# re-apply if your policy expects it: sudo chattr +i /etc/shadow
4. Remount writable / clear a stale lock if /etc is read-only or a lock lingers:
sudo rm -f /etc/shadow.lock # only if no passwd/usermod is running
sudo mount -o remount,rw / # for read-only rootfs cases
Hardening the host
- Do not apply local aging policy to directory-backed accounts — it silently does nothing useful and masks the real policy location.
- Editing
/etc/shadowby hand risks corruption; preferchage,passwd, andpwconv. - Service/system accounts often should be locked (
passwd -l) with no expiry rather than aged — decide policy per account type. - If you set
+ion shadow as a hardening measure, document it, or routine password changes will mysteriously fail.
Related system errors
- Auditing PAM and Password Policy with AI
- pam_faillock ‘Account Locked’ Error Guide
- CIS Benchmark Hardening for Linux Servers
Fixed it? Get 500 DevOps Security & Hardening & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Stuck on this? Start guided troubleshooting
Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.
Did this fix your issue?
Solved it a different way?
Share the fix that worked for you — reviewed, then published to help the next engineer.
That looks like it may contain a secret (key, token, password, or connection string). Please remove it — a note with a detected secret can’t be published.
Thanks — that helps. Published notes appear after a quick review.
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4Transport endpoint is not connected
- 5modprobe: FATAL: Module not found
- 6mount: wrong fs type, bad option, bad superblock
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.