Home Java INSTALL_FAILED_INSUFFICIENT_STORAGE — Free /data
Beginner 5 min · September 23, 2026

INSTALL_FAILED_INSUFFICIENT_STORAGE — Free /data

INSTALL_FAILED_INSUFFICIENT_STORAGE means /data is full.

N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Lessons pulled from things that broke in production.

Follow
Production
production tested
September 23, 2026
last updated
1,905
articles · all by Naren
Before you start⏱ 9 min
  • Basic adb commands
  • Android app install flow
  • Reading disk usage output
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • INSTALL_FAILED_INSUFFICIENT_STORAGE means the /data partition cannot fit your APK — it is a disk problem, not a code bug
  • Diagnose first with adb shell df /data; under 200 MB free (or 100% use) explains every symptom
  • Top hogs: forgotten debug variants, gigabyte caches, old APKs, and uninstall -k data remnants
  • Free /data specifically — clearing photos from /sdcard changes nothing for installs
  • android:installLocation is only a hint and needs external storage; App Bundles cut size 20 to 40%
✦ Definition~90s read
What is Android Insufficient Storage Install Fix?

INSTALL_FAILED_INSUFFICIENT_STORAGE is the Android package manager's verdict that the APK does not fit on the /data partition. It surfaces from adb install as Failure with that exact token, and on-device as an install error when the store or package installer gives up. The APK is typically fine; the destination disk is not.

Think of your phone's app storage as a parking garage.

The accounting covers more than the APK bytes. The package manager needs room for the APK copy, extracted native libraries, the app's data directory, and optimized dex output — all on /data, all at once. That is why installs fail with some space apparently free: the headroom requirement exceeds the visible margin, especially for large APKs on nearly-full partitions.

Beginners confuse this failure with three unrelated ones. A corrupt APK fails with a parse error, not a storage error. A signature clash with the installed version fails on certificates. A permission or manifest problem fails at a different install stage. Only genuine shortage produces the INSUFFICIENT_STORAGE token — read it literally.

The installLocation manifest attribute modulates where the app may go but does not create space: internalOnly, auto, and preferExternal are placement hints subject to system policy and app capability. Real remedies either free /data bytes or shrink the APK through bundles and asset discipline. Everything else is commentary on a full disk.

Plain-English First

Think of your phone's app storage as a parking garage. Each app is a car, and your new app is a truck looking for a spot. The garage is full — six abandoned demo cars, boxes of old files, no free spaces. The attendant (the package manager) turns your truck away with this error. The fix is not rebuilding the truck smaller (though that helps); it is towing the abandoned cars and clearing the boxes. Check the garage display (df), not the engine.

You run adb install, and instead of Success you get Failure [INSTALL_FAILED_INSUFFICIENT_STORAGE]. The APK is fine — it installed yesterday. Nothing in your code changed. The device just quietly ran out of room, and the package manager is telling you so in its least helpful voice.

This error is pure infrastructure: the /data partition where Android installs apps has less free space than your APK needs. The causes are mundane — six forgotten debug variants, a gigabyte of cached thumbnails, an emulator image sized for 2019 — but the confusion they create is real, because developers instinctively blame code for what is a disk problem.

The misdiagnosis tax is what hurts. Teams rewrite install logic, toggle manifest flags, and regenerate signing keys while df would have shown 0 KB free in ten seconds. Worse, some keep the -k uninstall flag out of habit, preserving the very data directories that keep the partition full across reinstalls.

This article makes the diagnosis mechanical: check /data with df, find the hog with du and package lists, free the right partition, and know what installLocation can and cannot do. Ten minutes of partition hygiene beats a day of code archaeology.

Where Installs Live: the /data Partition Budget

Android installs APKs onto the /data partition: the APK file, its extracted libraries, the data directory, and the Dalvik cache entries all consume /data bytes. When free space on /data drops below what the package manager needs — roughly the APK size plus working headroom — the install aborts with INSTALL_FAILED_INSUFFICIENT_STORAGE before copying a single byte.

The threshold bites earlier than developers expect. A 90 MB APK needs noticeably more than 90 MB free because extraction, dex optimization, and directory creation all draw from the same partition simultaneously. Devices showing 150 MB free can still fail a large install, which is why the 200 MB rule of thumb exists.

Two partitions confuse every diagnosis. Media, downloads, and photos live on /sdcard (often emulated from the same flash but accounted separately), while apps live on /data. Users who proudly free 2 GB of photos change /sdcard and watch the install fail identically — the package manager never looks there.

In code, File.getUsableSpace() reports what the app itself can use, which is handy for pre-flight checks before large downloads. But for install failures the authoritative view is outside the app: adb shell df /data shows the partition truth no app-level API can explain away.

StorageCheck.javaJAVA
1
2
3
4
5
6
7
8
public class StorageCheck {
    public static boolean hasRoom(File dir, long neededBytes) {
        long free = dir.getUsableSpace();
        System.out.println("free: " + free / 1024 / 1024 + " MB in " + dir);
        return free > neededBytes;
    }
}
📊 Production Insight
A 90 MB APK failed on devices showing 150 MB free until the team learned extraction needs headroom. Rule: treat under 200 MB free on /data as effectively full for install purposes.
🎯 Key Takeaway
/data holds the APK, libraries, data dir, and dex output — installs need APK size plus headroom, and only /data free space counts.

Stale Debug Builds: the Slow Leak on Every Test Phone

Development devices accumulate builds the way desks accumulate cables. Each feature branch gets installed for testing, the branch merges, and the build stays — 90 MB of APK plus data, forever. Six months of branches on a 16 GB test phone consumes gigabytes before anyone notices.

Demo and variant builds multiply the damage. Debug, staging, and production variants of the same app install as separate packages with separate data directories. A tester carrying all three plus last month's demo holds four copies of one app's footprint.

Old APK files add a second layer. Downloaded APKs sitting in Downloads consume /data on most devices (emulated storage draws from the same pool), and CI artifacts pushed to the device for manual installs pile up invisibly.

The fix is inventory plus routine. List packages matching your company prefix, match them against live branches, and uninstall the dead ones. Put device cleanup in the definition of done for merged branches: the branch dies, its builds die with it. Five or fewer test builds per device is a sustainable ceiling. Budget generously on low-end devices: system updates and dex optimization temporarily consume extra /data during installs, so a device idling at 300 MB free can still fail a 100 MB APK mid-write.

📊 Production Insight
One test phone held 11 forgotten branch variants totaling 1.2 GB. Rule: cap test devices at five builds and make branch-merge cleanup part of done.
🎯 Key Takeaway
Branch builds outlive their branches and stack up gigabytes. Inventory by package prefix and uninstall dead variants on merge.

Uninstall -k Remnants and Cache Bloat

The -k flag on adb uninstall keeps the app's data directory while removing the APK. It exists for testing backup and restore flows — and it gets used out of habit far beyond that purpose. Every habitual -k uninstall preserves caches, databases, and downloaded files that keep the partition full.

The trap is that reinstalling after -k inherits everything. The new build lands in the old data directory with its gigabytes intact, so the storage pressure that motivated the reinstall survives it. Developers then conclude the new build is bigger or broken, when the directory is simply uncleaned.

Caches deserve their own mention because the system may not clear them promptly. WebViews, image loaders, and HTTP caches grow into hundreds of megabytes on heavy test devices, and trim-caches runs only under system pressure. A deliberate pm trim-caches or in-app eviction policy reclaims this space deterministically.

Default to full uninstalls. Use plain adb uninstall with no flags for routine reinstalls, and reserve -k for the specific test session that needs kept data — documenting why in the test notes. When inheriting a device, pm clear on stale packages is the fastest honest reset. Photograph the drawer before deleting so testers can reinstall what they still need.

CacheJanitor.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CacheJanitor {
    public static long clearCaches(File cacheDir, long olderThanMs) {
        long freed = 0;
        long cutoff = System.currentTimeMillis() - olderThanMs;
        File[] files = cacheDir.listFiles();
        if (files == null) {
            return 0;
        }
        for (File f : files) {
            if (f.lastModified() < cutoff && f.delete()) {
                freed += 1;
            }
        }
        return freed;
    }
}
📊 Production Insight
A team reinstalled over -k remnants for weeks, convinced each build grew fatter. Rule: when storage misbehaves, pm clear or full uninstall first — inherit nothing.
🎯 Key Takeaway
Routine -k uninstalls preserve the data hogging the partition. Default to full uninstalls; reserve -k for deliberate backup tests.

Diagnosing With df, du, and Dumpsys

The diagnostic sequence takes two minutes. First, adb shell df -h /data shows partition truth: use percentage and free bytes. Compare free bytes against your APK size — if the APK does not fit with headroom, the case is closed and every further step is cleanup, not debugging.

Second, rank the hogs. Dumpsys package lists and du over /data/data rank residents by size; pm list packages filtered by your prefix finds forgotten variants. The top entries usually explain 80% of the pressure: one giant game, three stale builds, a runaway cache.

Third, reclaim precisely. pm trim-caches with a size argument reclaims cache space system-wide without touching user data. Targeted uninstalls remove dead builds. Clearing a single app's oversized cache from Settings handles the outlier without collateral damage.

In-app, StatFs on the files directory reports what the app can actually use, which powers honest pre-download checks and trimmed-down offline modes. Log the numbers: a support ticket saying install failed with 40 MB free on /data resolves itself, and one saying 4 GB free points at signatures or corrupt APKs instead. Schedule the eviction policy to run on every app start so caches never grow unchecked again.

SpaceProbe.javaJAVA
1
2
3
4
5
6
7
8
9
10
public class SpaceProbe {
    public static void report(Context ctx) {
        StatFs stat = new StatFs(ctx.getFilesDir().getPath());
        long free = stat.getAvailableBytes();
        System.out.println("app-available MB: " + free / 1024 / 1024);
        System.out.println("cache: " + ctx.getCacheDir().getAbsolutePath());
        System.out.println("files: " + ctx.getFilesDir().getAbsolutePath());
    }
}
📊 Production Insight
Support tickets with attached df output resolved 3x faster than those without. Rule: teach support the one df command — partition numbers end storage arguments instantly.
🎯 Key Takeaway
df proves fullness, du ranks hogs, trim-caches reclaims safely. Compare APK size to free bytes before any code theory.

installLocation and App Bundles: What Actually Shrinks Installs

The android:installLocation manifest attribute declares where the app may live: internalOnly, auto, or preferExternal. It reads like a fix for full /data, but it is a hint the system may ignore — and it helps only when external storage exists and the app supports it. Most modern devices emulate external storage from the same flash anyway.

Widgets, services, and alarm-driven apps must stay internal regardless of the flag; the system will refuse to move them. Apps using certain account and sync features face the same restriction. Setting preferExternal on such apps changes nothing while implying a promise the platform will not keep.

The reliable size lever is the App Bundle. Publishing bundles lets the store generate per-device APKs with only the needed density, ABI, and language splits — typically 20 to 40% smaller downloads. A smaller APK fits where a bloated universal fails, on every partition, with no manifest gambling.

Treat installLocation as documentation of intent and bundles as the actual optimization. Set the attribute honestly, publish bundles always, track download size in CI, and keep /data hygiene as the operational backstop. No manifest flag substitutes for free bytes.

📊 Production Insight
Switching to bundles cut one app's install from 96 MB to 61 MB and ended marginal-device failures. Rule: alert on 10% APK growth in CI — size regressions are install failures scheduled for later.
🎯 Key Takeaway
installLocation is an ignorable hint; App Bundles genuinely shrink installs 20 to 40%. Track size in CI and publish bundles.

Prevention: Budgets, Gates, and Hygiene That Hold

Prevention is a checklist, not a skill. For developers: cap test-device builds, default to full uninstalls, and check df before theorizing. For CI farms: gate suites on free space, uninstall test APKs post-run, and track APK size with growth alerts. For releases: publish bundles and test installs on low-end devices with nearly-full storage.

For users hitting the error on their own phones, the guidance is concrete: clear cached data from Settings, uninstall unused apps, delete downloaded APKs, and move media off-device. Each step names /data residents — vague advice to free space sends users to delete photos that do not matter.

Large-footprint features deserve budgets. Offline maps, media packs, and ML models should declare their megabytes, check usable space before downloading, and degrade gracefully when room is short. A guarded download that says need 400 MB, have 120 MB beats a crash every time.

The cultural fix is treating device storage as a monitored resource. Dashboards track it on farms, checklists cover it in QA, and support asks for it in tickets. Storage stops being anyone's problem only when it becomes everyone's metric. Pair the attribute with App Bundle publishing so the declaration and the size win ship together.

DownloadGuard.javaJAVA
1
2
3
4
5
6
7
public class DownloadGuard {
    public static boolean canDownload(File dir, long bytes) {
        long headroom = 50L * 1024 * 1024;
        return dir.getUsableSpace() > bytes + headroom;
    }
}
🔥Check /data, Not /sdcard
Freeing /sdcard photos never fixes installs — the package manager only cares about /data. Check the right partition first, every time.
📊 Production Insight
A pre-suite df gate under 500 MB ended an entire class of flaky farm failures overnight. Rule: fail fast with a clear disk message instead of failing mysteriously mid-install.
🎯 Key Takeaway
Cap builds, gate farms on free space, publish bundles, budget big downloads, and monitor storage as a first-class metric.
● Production incidentPOST-MORTEMseverity: high

A Full Device Farm Failed 60% of Installs for 3 Weeks Unnoticed

Symptom
Overnight suites went from 98% green to 40% red with install failures on every app, not just the merged feature. Reruns failed identically. Local installs on developers' desks worked fine, which deepened the regression theory — desks had free space, the farm did not.
Assumption
The lab dashboard showed devices online and healthy — nobody monitored disk, only connectivity. Each suite installed 3 fresh APKs per device per run and never uninstalled, because cleanup was considered wasted time. The failure looked like app regression since it arrived with a Monday merge, so two engineers spent a day bisecting commits.
Root cause
Twenty shared test devices accumulated 3 weeks of un cleaned test APKs — roughly 45 installs per device at 90 MB each, over 4 GB per phone — until /data hit 100%. Monday's suite run failed 60% of installs with INSTALL_FAILED_INSUFFICIENT_STORAGE across 12 of the 20 devices. The timing coincided with a large feature merge, so the failures were triaged as app regression and a full day went to commit bisection before someone ran df and found 0 KB free.
Fix
The lab added a pre-suite df gate that fails fast with a clear message when /data drops under 500 MB, plus post-suite uninstall of every test APK. APK size tracking in CI flagged a 40% asset bloat the same week, and switching test distribution to App Bundles cut install size by a third. Suite reliability returned to 99% within 2 days and the phantom regression was closed.
Key lesson
  • Monitor disk on test devices like any other resource — connectivity-green plus disk-full produces failures that look exactly like app regressions.
  • Uninstall test APKs after every suite run; installation without cleanup is a slow leak with a pager attached.
  • Track APK size in CI with growth alerts, because a 40% fatter APK turns a comfortable device into a failing one silently.
Production debug guideFive checks that find the hog before you rewrite a line of code.5 entries
Symptom · 01
adb install fails with INSUFFICIENT_STORAGE
Fix
Run adb shell df -h /data /sdcard and compare free bytes against your APK size from ls -lh app/build/outputs/apk/debug/*.apk. If /data shows under 200 MB free or 100% use, stop debugging code — free /data first.
Symptom · 02
Finding which builds hog the partition
Fix
Run adb shell pm list packages | grep -i yourcompany and adb shell du -sh /data/data/your.package. Forgotten branch variants and bloated data dirs show up here. Uninstall dead variants with adb uninstall (no -k).
Symptom · 03
Suspecting uninstall -k remnants
Fix
Run adb shell dumpsys package your.package | grep -A 5 dataDir after a -k uninstall. If the data directory survived, clear it with adb shell pm clear your.package or reinstall with a full adb uninstall first.
Symptom · 04
Needing fast space without deleting user data
Fix
Run adb shell du -sh /data/data/* 2>/dev/null | sort -rh | head -10 to rank data hogs. Clear the worst caches with adb shell pm trim-caches 1G, which reclaims cache space across apps without deleting user data.
Symptom · 05
Emulator installs failing on a fresh-looking image
Fix
Open the AVD manager, show advanced settings, and raise Internal Storage to 4096 MB or more; or run adb shell df /data on the emulator to confirm. Wipe-data resets a bloated virtual disk when snapshots have grown out of control.
INSTALL_FAILED_INSUFFICIENT_STORAGE Causes Compared
Root CauseHow to ConfirmFixPrevention
/data partition genuinely fulladb shell df /data shows 100% use or under 200 MB freeFree space: uninstall apps, clear caches, delete APKsMonitor free space in CI device farms before suites
Stale debug builds hoarding spaceadb shell pm list packages | grep your prefix shows forgotten variantsUninstall dead variants; keep five or fewer on deviceName branch builds clearly; uninstall on merge
uninstall -k data remnantsPackage reinstall inherits old data dir; dumpsys shows leftover dataadb uninstall without -k, or clear app data firstReserve -k for deliberate backup-restore tests only
APK larger than free spaceAPK size from ls -lh exceeds df free bytes on /dataShrink with App Bundle, or free more spaceTrack APK size in CI; alert on 10% growth
Wrong partition blamed/sdcard has room while /data is full; install still failsFree /data specifically — caches, apps, dalvik leftoversCheck both partitions; installs only need /data
⚙ Quick Reference
4 commands from this guide
FileCommand / CodePurpose
StorageCheck.javapublic class StorageCheck {Where Installs Live
CacheJanitor.javapublic class CacheJanitor {Uninstall -k Remnants and Cache Bloat
SpaceProbe.javapublic class SpaceProbe {Diagnosing With df, du, and Dumpsys
DownloadGuard.javapublic class DownloadGuard {Prevention

Key takeaways

1
The error means /data cannot fit the APK
diagnose with adb shell df /data before touching code.
2
Stale debug builds and -k remnants are the top space hogs on dev devices.
3
Free the /data partition specifically; /sdcard room does not help installs.
4
android:installLocation is a hint, not a fix
and only helps with external storage.
5
App Bundles cut install size 20 to 40% and prevent marginal failures.
6
Track APK size and farm free space in CI so installs never flake on a full disk.

Common mistakes to avoid

5 patterns
×

Rewriting install code when the disk is simply full

Symptom
Hours spent changing install flags and manifest entries while every install still fails. The df output would have shown 0 KB available in the first minute.
Fix
Read the device error or run adb shell df /data before changing code. If /data shows 100% use, free space first: uninstall stale builds, clear app caches, delete old APKs. Code changes cannot fix a full disk.
×

Reinstalling over -k remnants and stale debug data

Symptom
Fresh install still fails or behaves like the old build. The package manager keeps the data directory from the kept-data uninstall, so the new install inherits the old storage pressure.
Fix
Uninstall fully with adb uninstall your.package (no -k) to remove data remnants, or clear the app's data from Settings before reinstalling. Keep -k only for deliberate backup-restore testing.
×

Hoarding debug builds on a small test device

Symptom
Six variants of the same app plus old APKs consume 3 GB on a 16 GB device. New installs fail while the drawer overflows with forgotten demo builds.
Fix
Keep five or fewer debug builds on test devices, and uninstall feature-branch builds when the branch merges. Name builds clearly so stale ones are obvious in the app drawer.
×

Clearing photos from /sdcard when /data is the full partition

Symptom
User deletes 2 GB of photos, install still fails. Android installs to /data, so only space on /data matters for INSTALL_FAILED_INSUFFICIENT_STORAGE.
Fix
Delete leftover APKs and move media to external storage before installing. Check adb shell df /data and /sdcard separately — freeing the wrong partition changes nothing.
×

Treating every install failure as a storage problem

Symptom
Storage is fine (df shows 4 GB free) but installs fail from a corrupt APK or a signature clash with the Play version. The storage fix is applied to a signing problem.
Fix
Read the full adb install output and logcat lines around PackageManager. Parse errors, signature mismatches, and permission failures each have distinct messages — match the message before choosing the fix.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01JUNIOR
What does INSTALL_FAILED_INSUFFICIENT_STORAGE mean?
Q02SENIOR
How do uninstall -k remnants cause repeat failures?
Q03SENIOR
Which adb commands diagnose a full device?
Q04SENIOR
What does android:installLocation do and what are its limits?
Q05SENIOR
Keep a CI device farm free of storage-flaky installs.
Q01 of 05JUNIOR

What does INSTALL_FAILED_INSUFFICIENT_STORAGE mean?

ANSWER
It means the PackageManager could not fit the APK on the /data partition: either the partition is full or the APK is larger than the free space. You confirm with adb shell df /data and fix it by freeing space on that partition.
FAQ · 6 QUESTIONS

Frequently Asked Questions

01
Will freeing space on my development machine help?
02
How do I fix this on an emulator?
03
What does adb uninstall -k actually keep behind?
04
Do App Bundles reduce this failure?
05
Does android:installLocation fix a full /data?
06
What should users do when they hit this on their own phones?
N
Naren Founder & Principal Engineer

20+ years shipping production Java in banking & fintech. Lessons pulled from things that broke in production.

Follow
Verified
production tested
September 23, 2026
last updated
1,905
articles · all by Naren
🔥

That's Android. Mark it forged?

5 min read · try the examples if you haven't

Previous
Android Cleartext HTTP Fix
3 / 3 · Android
Next
Java FileNotFoundException Fix