When a Mac App Will Not Uninstall: Seven Causes to Check
A failed uninstall on macOS is not one problem. Finder can refuse to move the bundle. The move can succeed and the app can be back at the next login. The bundle can vanish while the helper that annoyed you keeps running. Each is a different mechanism with a different fix, so start from the exact thing your Mac did. For the ordinary sequence, see complete uninstall; what follows assumes that already failed.
Start from the symptom
- "The item can't be moved to the Trash because it's open." Something is running, often not the app you quit.
- It was deleted, and it is back. Check whether the bundle was reinstalled or only a surviving helper restarted. Those need different fixes.
- Finder asks for an administrator password. A
.pkgleft the bundle owned by root. Normal. - Nothing happens. No dialog, no error. App Management permission is one possible cause.
rmas root says "Operation not permitted". A protection or permission restriction; the message alone does not identify SIP.- Greyed out, or it reappears on a work Mac. A configuration profile or MDM owns it.
1. The app, or one of its helpers, is still running
Finder refuses to move a bundle whose files are open, and quitting the process you can see
is not stopping everything the app started. Activity Monitor lists every process, not only
the ones with a window. Search the vendor name and read the whole result set: an app called
Foo commonly ships Foo Helper, a FooUpdater, and a login-item bundle with an unrelated
display name. The Apple menu > Force Quit window is no substitute, because it lists
only applications with a UI presence.
pgrep -fl -i foo
lsof +D /Applications/Foo.app 2>/dev/null | awk '{print $1, $2}' | sort -u
pgrep -fl matches the full command line, so it catches a helper whose executable path
carries the vendor name even when its process name does not. lsof +D reports every
process holding a file inside the bundle.
Force quitting the parent does not reliably stop a helper. A helper is its own process with its own PID, so killing the parent orphans it unless the parent tears it down on exit. And if launchd manages the helper, killing either one only tells launchd to start it again. That is the next section.
A Quick Look preview or Spotlight indexing can hold files in the bundle too, and a restart clears both. If the message returns, Apple's app removal guide suggests Safe Mode.
2. A launchd agent or daemon restarts a surviving helper
If an icon or helper returns, first check whether its executable still exists outside the deleted bundle. launchd can restart that program, but cannot restore a deleted app bundle on its own. A quiet Activity Monitor snapshot does not rule out an on-demand job.
launchd supervises background jobs. A job is a property list with a Label, a program,
and conditions for running it. RunAtLoad starts it when the job loads, KeepAlive
restarts it when it exits. A job with neither still comes back: MachServices, Sockets,
WatchPaths, QueueDirectories, and StartInterval all make launchd start the process
the moment something asks for it, so a helper that idles out after ten seconds and
restarts on its Mach service looks absent every time you check.
Definitions live in three places. ~/Library/LaunchAgents is your user only, inside your
login session; /Library/LaunchAgents runs for every user at login; and
/Library/LaunchDaemons holds system-wide jobs that can run without a login. They use
root by default but can specify another user. Either agents or daemons can survive a
manual uninstall if installed outside the bundle. /System/Library/Launch* is
Apple's and protected.
launchctl list | grep -i foo
launchctl print-disabled gui/$(id -u) | grep -i foo
grep -l -i foo ~/Library/LaunchAgents/*.plist /Library/LaunchAgents/*.plist \
/Library/LaunchDaemons/*.plist 2>/dev/null
In launchctl list, a label with a PID is running now and one with a dash is loaded and
waiting for a trigger; print-disabled reads the persistent disabled-state database, a
separate fact from whether a plist exists. Read the candidate with plutil -p <path> and
check that Program or ProgramArguments points at the app you are removing: vendors do
not always name the file after the label inside it.
The order matters
Stop and disable the job first, then remove the plist, then remove the app.
launchctl bootout gui/$(id -u)/com.vendor.foo.helper
sudo launchctl bootout system/com.vendor.foo.daemon
launchctl disable gui/$(id -u)/com.vendor.foo.helper
Delete the plist while the job is loaded and launchd keeps a service whose definition no longer exists on disk; it runs until the next reboot and can leave a stale entry in the disabled-state database. Removing the app first is worse: the job respawns against a missing executable and fails in a loop, which is where "it is gone but still shows in Login Items" comes from.
On macOS 13 and later, apps can register through
SMAppService
and keep the helper executable and service files inside the app bundle, so there may
be no standalone plist in the directories above. The registration itself is managed by macOS.
Those belong to Background Task Management, controlled in
System Settings > General > Login Items & Extensions
(startup items guide).
3. It is a system app protected by SIP
System Integrity Protection is a kernel-level policy, not a permission bit. Apple
describes it as using kernel permissions to limit writability of critical system files,
applied "to every process running on the system, regardless of whether that process is
running sandboxed or with administrative privileges"
(Apple Platform Security).
Since Big Sur the system content also sits on a separate, cryptographically sealed volume.
csrutil status prints whether protection is on, and Apple is explicit that "you can't
remove apps that are required by your Mac", a set that includes Mail, Music, Books, Notes,
Podcasts, Maps, News, and Stocks.
Turning SIP off to delete one bundle is a bad trade. It means booting to Recovery and changing a machine-wide security policy; on Intel Macs, Apple notes that disabling it removes protection for every partition on the physical storage device, and on Apple silicon the Mac leaves Full Security. The win does not last either: the system volume is replaced wholesale at the next macOS update, and no usable space is reclaimed.
Better: drag the icon out of the Dock, remove it from System Settings > General > Login Items & Extensions, and if it keeps opening your files, change the handler with Get Info > Open with > Change All.
4. It was installed by MDM or a configuration profile
On a managed Mac an app can be pushed back on the management server's schedule, and a profile can be marked non-removable. The symptoms are a removal that undoes itself hours later, a greyed-out control, or a launchd search that finds nothing because the reinstall is driven remotely. Check System Settings > General > Device Management; if that section is absent, do not treat that alone as proof that the Mac is unmanaged. Check enrollment status and ask IT on an organization-owned Mac.
profiles status -type enrollment
sudo profiles list
The first reports enrollment through Automated Device Enrollment and whether it is user approved; the second lists installed profiles and needs root. Then ask IT. Apple's guidance is to ask whoever provided a profile you cannot remove, and it warns that removing a profile deletes everything that profile configured, so one carrying your mail account takes that with it.
5. Ownership, and the permission that fails silently
Finder asks for an administrator password. Ordinary. A .pkg installer runs as root
and leaves the bundle owned by root, so moving it needs authentication. Confirm with
ls -ld /Applications/Foo.app. Receipts are worth knowing while you are here:
pkgutil --files <id> lists the paths a package placed, and sudo pkgutil --forget <id>
drops the receipt from /private/var/db/receipts without deleting a single file.
Nothing happens at all. No prompt, no error, the app is still in /Applications, and
the tool you used reports a vague failure or falls back to something else. On macOS 14 and
later App Management is one possible cause: it controls whether an app may update or
delete other apps. This read-only test checks whether the bundle path is writable:
test -w /Applications/Foo.app && echo "posix says yes"
That result does not rule out a permission problem. Removal also depends on the parent directory's write and search permissions, ACLs, and other protections. If App Management is denied, open System Settings > Privacy & Security > App Management, enable the trusted app doing the removal, then relaunch it and retry.
Under the hood: three refusals that look the same
File permissions are one gate: ownership, parent-directory access, and ACLs can affect
removal. Administrator authorization can help with some restrictions, not all of them.
TCC, the privacy layer behind System Settings, adds a separate check. App Management
is a TCC gate for one operation, modifying or deleting another app's bundle. Being an
administrator does not satisfy it and neither does sudo, because it is keyed to the
requesting program rather than the user, which is why its denial can surface as a generic
error with no prompt.
SIP can refuse even root, but error wording alone does not identify the protection.
EACCES (Permission denied) can include missing write or search access to a parent
directory. EPERM (Operation not permitted) has causes besides SIP. Check the exact
path, ownership, parent-directory permissions, and requesting app before choosing a fix;
neither message is a reason to disable system protection.
6. A system extension or network filter is still active
Security software, VPN clients, and virtualization products install system extensions. The containing app registers the extension, and deleting individual files is not a reliable deactivation procedure. macOS can remove a system extension when its containing app is properly moved to the Trash, but vendor software may have other installed components. Use the vendor's removal procedure and verify the resulting state.
systemextensionsctl list
The output shows team identifier, bundle identifier, and a state such as
[activated enabled]. Deactivation belongs to the containing app and often needs a restart,
so run the vendor's uninstaller first.
Uninstalling antivirus on Mac covers the teardown
order for this class.
7. It came from the App Store, or from Homebrew
Mac App Store apps. Deleting the bundle does not remove the purchase. The case that catches people is the setting Apple words as "Automatically download apps that you purchased from the App Store on other Mac computers and devices": if a second Mac on the same account purchases an app on another device, the setting can download that purchase. Simply keeping an app installed on a second Mac does not by itself prove a reinstall cause. Check the setting in App Store > Settings.
Homebrew casks. If you installed with brew install --cask foo, trashing the app
leaves Homebrew believing it is installed. brew list --cask still shows the token, and
the next brew upgrade can reinstall the app you just deleted, a real "it came back" cause
with no launchd job involved. Run brew uninstall --cask foo instead. Homebrew's manpage
describes --zap as removing "all files associated with a cask" and warns it "may remove
files which are shared between applications", so reach for that one deliberately.
After a successful delete: what stays behind
Login Items & Extensions still lists it. Either an "Open at Login" entry pointing at a missing path, or a Background Task Management record for a service whose program is gone. Remove it with the minus button in System Settings > General > Login Items & Extensions; macOS often clears these itself after a restart.
A menu bar icon appears at boot. Something still loads a binary: usually a launch agent
you never removed, or a helper the installer copied into
~/Library/Application Support/<vendor>.
A privileged helper survives. Software that needed root installs into
/Library/PrivilegedHelperTools/<label> with a matching
/Library/LaunchDaemons/<label>.plist. Both are root-owned and outside the bundle, so
trashing the app touches neither.
ls -la ~/Library/LaunchAgents /Library/LaunchAgents /Library/LaunchDaemons \
/Library/PrivilegedHelperTools 2>/dev/null
For the data side, see leftover files after uninstalling.
Doing this diagnosis in Mole
The manual version of this article costs five screens: Activity Monitor, three launchd folders, Login Items & Extensions, Privacy & Security, and Finder. Mole puts the parts belonging to one app on one tab, and scanning is always free, so it works as a read-only diagnostic whether or not you buy it.
Open Mole's Software tab. It holds three segments: the installed app inventory, available updates, and startup items. That last one is the launchd and login-item inventory this article told you to assemble by hand, so the "it comes back" cause is visible before you delete rather than after.
Select an app and Mole resolves its bundle identifier, then finds what that identity owns: Application Support, Caches, Preferences, Containers, HTTPStorages, and launch agents or daemons whose plist actually references the app rather than merely sharing a word with its name. Each candidate carries its path, size, and the evidence that attached it, and anything low-confidence arrives unchecked.
Confirming runs the order this article recommends, enforced rather than remembered. Mole
quits the app and the helpers nested inside its bundle, boots out its login-item helpers,
unloads any approved launch item through launchctl before its plist is removed, and
validates every path again at deletion time. Ordinary file removals go to the Trash;
files still there can usually be restored, but restoring them is not a full undo of the uninstall.
Then Mole reports skipped and failed items with their paths instead of a success total, so
a row refused because App Management is denied, or because a path is root-owned and the
guard rejected it, tells you which cause above you just hit. A tool that prints a
checkmark over a refused write is why people spend an evening wondering about a menu bar
icon. Everything Mole does runs locally, and file operations append to
~/Library/Logs/mole/operations.log. In a terminal,
Mole CLI is free and open source, and mo uninstall takes
--dry-run so you can read the path list first.
Mole does not fight the three causes it cannot win: it will not disable SIP or remove a stock Apple app from the sealed volume, it cannot override a configuration profile that reinstalls software on a managed Mac, and for security agents, VPN clients, and virtualization products it is not a substitute for the vendor uninstaller that knows the teardown order. When App Management is denied, Mole reports the failure rather than escalating privileges around it.
FAQ
Why does an app come back after I delete it?
First distinguish a reinstalled app bundle from a restarted helper. launchd can restart
an executable that still exists, not recreate a deleted bundle. A Homebrew cask record
may have survived because you trashed the app instead of running
brew uninstall --cask. On a managed Mac, MDM pushed it back. Or the App Store setting for
automatically downloading purchases on other devices may explain a new download.
Can I delete Apple's built-in apps if I turn off SIP?
Disabling SIP alone does not make the sealed system volume writable. Trying to remove required system apps can involve weakening additional protections and is not a supported cleanup method. Remove an unwanted icon from the Dock or Login Items instead.
Finder asks for my password to delete an app. Is something wrong?
No. A .pkg installer put the bundle there as root, so moving it needs authentication.
The failure worth worrying about is the opposite: no prompt, no error, nothing happens.
App Management being denied under System Settings > Privacy & Security is one possible cause,
and sudo does not fix it, because the gate is keyed to the program asking rather than to
the user.
Related reading
- How to completely uninstall apps on Mac for the normal sequence and the Library layers it reviews.
- How to uninstall antivirus on Mac for software with system extensions, where teardown order is the whole job.
- How to disable startup programs on Mac for the launchd and Login Items side once nothing is fighting you.