Ansible Error Guide: 'Could not get lock /var/lib/dpkg/lock' apt Module Failure
Fix Ansible's apt 'Failed to lock apt for exclusive operation / Could not get lock /var/lib/dpkg/lock-frontend' error: diagnose concurrent apt, unattended-upgrades, and stale locks.
- #ansible
- #troubleshooting
- #errors
- #apt
Exact Error Message
fatal: [web-01]: FAILED! => {
"changed": false,
"msg": "Failed to lock apt for exclusive operation: Could not get lock /var/lib/dpkg/lock-frontend.
It is held by process 1432 (unattended-upgr)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?"
}
You may also see Could not get lock /var/lib/apt/lists/lock or /var/lib/dpkg/lock, all variations of the same exclusive-lock problem from the apt module.
What the Error Means
Debian/Ubuntu’s package tooling (dpkg and apt) takes exclusive file locks so that only one package operation runs at a time. Ansible’s apt module wraps these tools, so when it tries to install or update packages while another process already holds the lock, it cannot proceed and fails immediately with Failed to lock apt for exclusive operation.
The error helpfully names the holding process when it can (here, unattended-upgr). This is a contention problem, not a broken package, and it is extremely common on freshly booted cloud instances where automatic updates run on startup.
Common Causes
unattended-upgradesis running automatic security updates in the background, especially in the first minutes after boot.- Another
apt/dpkgprocess (a manual session, cloud-init, or a parallel Ansible run) holds the lock. - Two Ansible plays target the same host simultaneously (high
forksplus per-host package tasks). - A previous
apt/dpkginvocation crashed and left a stale lock file behind. dpkgwas interrupted mid-operation and the database needsdpkg --configure -a.
How to Reproduce the Error
Run an apt task on a host that is still applying boot-time updates:
- hosts: web
become: true
tasks:
- name: Install nginx
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
ansible-playbook web.yml -i inventory.ini --diff -vvv
fatal: [web-01]: FAILED! => {"changed": false, "msg": "Failed to lock apt for exclusive operation: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1432 (unattended-upgr)"}
Diagnostic Commands
Confirm what holds the lock right now:
ansible web-01 -i inventory.ini -b -m command -a "lsof /var/lib/dpkg/lock-frontend"
Check whether unattended-upgrades or another apt process is active:
ansible web-01 -i inventory.ini -b -m command -a "ps aux | grep -E 'apt|dpkg|unattended'"
Inspect the dpkg state in case a previous run was interrupted:
ansible web-01 -i inventory.ini -b -m command -a "dpkg --audit"
Re-run the original play with verbosity to capture the exact lock path and holding PID:
ansible-playbook web.yml -i inventory.ini --diff -vvv
Step-by-Step Resolution
-
Identify the holder. If it is
unattended-upgror cloud-init, the right fix is usually to wait, not to kill it mid-update. -
Make the apt task wait for the lock instead of failing. The cleanest approach is to retry until the lock clears:
- name: Install nginx (wait out boot-time updates)
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
register: apt_result
until: apt_result is not failed
retries: 30
delay: 10
- Or wait for the lock file to be released before touching apt at all:
- name: Wait for apt lock to be released
ansible.builtin.shell: "while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do sleep 5; done"
changed_when: false
- If a previous run crashed and left things half-done, repair dpkg before continuing (verify the lock is genuinely stale first):
ansible web-01 -i inventory.ini -b -m command -a "dpkg --configure -a"
-
Avoid concurrent apt operations. Do not run two plays against the same host at once, and serialize package tasks if your inventory fans out heavily.
-
Re-run and confirm success:
ansible-playbook web.yml -i inventory.ini --diff
changed: [web-01]
Prevention and Best Practices
- Build retry/
untillogic into everyapttask so transient boot-time locks do not fail an otherwise healthy run. - On cloud images, either disable
unattended-upgradesduring provisioning or explicitly wait for cloud-init/apt to finish before running package tasks. - Never blindly delete lock files. Removing a lock that an active process holds can corrupt the dpkg database. Confirm the process is gone first.
- Serialize package operations per host; do not launch overlapping plays that both run apt against the same machines.
- Use
dpkg --auditanddpkg --configure -ato recover cleanly from interrupted installs rather than forcing locks. - Keep
update_cachedeliberate; pair it withcache_valid_timeto reduce how often you contend for the lists lock.
Related Errors
E: dpkg was interrupted, you must manually run 'dpkg --configure -a'— an interrupted install, often a precursor to lock contention.Could not get lock /var/lib/apt/lists/lock— contention on the package-lists lock specifically.MODULE FAILUREfrom the apt module — a different, lower-level failure rather than a lock.Timeout (12s) waiting for privilege escalation prompt— a become problem, not an apt lock.
Frequently Asked Questions
Can I just delete the lock file? Only if you have confirmed no process holds it (lsof/fuser show nothing). Deleting a lock held by a live process can corrupt the package database.
Why does this only happen right after boot? Cloud images run unattended-upgrades and cloud-init on startup, which hold the apt/dpkg locks for the first few minutes. Waiting them out resolves it.
What is the cleanest fix in a playbook? Add until: apt_result is not failed with retries and delay so the task waits for the lock to clear instead of failing on the first attempt.
How do I stop two plays from colliding? Do not run overlapping plays against the same hosts, and consider serial or per-host throttling for package-heavy roles. For more package and provisioning patterns, see the Ansible guides.
Download the Free 500-Prompt DevOps AI Toolkit
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.