GitHub Actions Runner Out of Disk Space: Fix in 5 Minutes
CI failing with 'No space left on device' on GitHub Actions or self-hosted runners? Here is exactly how to diagnose what's eating disk — Docker layers, build artifacts, or the runner's own accumulation — and fix it for good.
"No space left on device" mid-build is one of the more frustrating CI failures because the error surfaces wherever the disk happened to fill up — a docker build step, a npm install, a test run — not at the actual point where space was consumed. Here is how to find and fix the real cause.
Step 1: See What's Actually Eating Space
# Add this as an early debug step whenever disk issues are suspected
- name: Check disk space
run: |
df -h
du -sh /* 2>/dev/null | sort -rh | head -10
docker system df # If Docker is involvedOn GitHub-hosted runners, this is the fastest way to confirm you're actually hitting the runner's disk limit (typically ~14GB free on standard runners) rather than something else.
Cause 1: Docker Images/Layers Accumulating Across Jobs
docker system df
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
# Images 47 3 18.3GB 17.8GB (97%)
# Containers 12 1 245MB 240MB (98%)Every docker build and docker pull in a workflow leaves layers behind. On GitHub-hosted runners this resets each run, but on self-hosted runners this accumulates across every job that ever ran on that machine.
Fix — prune after builds, and add scheduled cleanup on self-hosted runners:
- name: Build image
run: docker build -t myapp .
- name: Clean up Docker
if: always()
run: docker system prune -af --volumes# On self-hosted runners, also add a scheduled cron cleanup independent of jobs
# (cron on the runner host itself)
0 3 * * * docker system prune -af --volumes --filter "until=24h"Cause 2: GitHub-Hosted Runner's Pre-Installed Software Eating Your Budget
Standard GitHub-hosted runners ship with a large amount of pre-installed software (multiple language runtimes, Android SDK, etc.) that you likely don't need for any given job — it eats into your usable disk before your job even starts.
- name: Free up disk space
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc
sudo rm -rf /opt/hostedtoolcache/CodeQL
df -hThis single step commonly frees 20-30GB on standard GitHub-hosted runners before your build even starts — worth adding as an early step in any workflow that's tight on space, rather than debugging it after the fact.
Cause 3: Build Artifacts and Cache Growing Unbounded
du -sh ~/.npm ~/.cache ~/.m2 ~/.gradle 2>/dev/null
# Package manager caches can silently grow to several GB over time,
# especially on self-hosted runners that persist between jobsFix — bound your cache size explicitly, don't let it grow forever:
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
# actions/cache itself has per-repo limits (10GB), but local caches
# on self-hosted runners need their own cleanup policy# On self-hosted runners — cap and periodically clear local package caches
npm cache clean --force
find ~/.m2/repository -type f -atime +30 -delete # Remove Maven artifacts unused in 30 daysCause 4: Test Artifacts, Coverage Reports, and Logs Never Cleaned Up
find . -name "*.log" -o -name "coverage" -o -name "test-results" | xargs du -sh 2>/dev/null | sort -rh | head -10On self-hosted runners, if actions/checkout isn't cleaning the workspace between runs (or jobs write outside the workspace), test artifacts from every historical run can accumulate.
Fix — ensure clean checkouts and explicit artifact cleanup:
- uses: actions/checkout@v4
with:
clean: true # Default true, but confirm it's not disabled
- name: Clean workspace after job
if: always()
run: rm -rf coverage/ test-results/ *.logCause 5: Self-Hosted Runner Disk Genuinely Too Small for the Workload
df -h /home/runner
# If you're consistently near capacity even after cleanup, the disk is
# undersized for what you're actually running (large monorepo, big Docker images)Fix — resize the underlying volume, don't just keep fighting cleanup:
# Example for a cloud VM-backed self-hosted runner
aws ec2 modify-volume --volume-id vol-0abc123 --size 100
sudo growpart /dev/xvda 1
sudo resize2fs /dev/xvda1If you're spending significant workflow time on cleanup steps every run, that's usually a signal the runner is undersized, not that you need cleverer pruning.
Diagnostic Checklist
df -h # overall disk usage
docker system df # Docker-specific breakdown
du -sh /* 2>/dev/null | sort -rh | head # top-level directory usage
du -sh ~/.npm ~/.cache ~/.m2 2>/dev/null # package manager cachesMore CI/CD troubleshooting? Read our GitHub Actions cache not working fix and Docker build slow no cache fix.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
GitHub Actions Artifact Upload Failing — Size Limit & Permissions Fix
Your GitHub Actions artifact upload is failing with 'upload artifact failed' or size limit errors. Here are the exact causes and fixes for the most common artifact upload failures.
GitHub Actions Cache Not Working — How to Fix It
Your workflow runs are still slow even with actions/cache. Cache miss every time, cache key conflicts, wrong paths — here's how to diagnose and fix GitHub Actions caching.
GitHub Actions Composite Action Inputs Not Working: How to Fix It
Composite action inputs returning empty strings, secrets not passing through, or steps failing silently? Here are the exact fixes for common composite action bugs.