quickstart →

Fix "No space left on device" in GitHub Actions

Fix "No space left on device" in GitHub Actions: see what fills the disk, free space on ubuntu-latest, use /mnt, and get a runner with a bigger disk.

A job fails with one of these, usually in a Docker build, a large npm install, an Android or ML build, or a test that writes a lot of data:

No space left on device
System.IO.IOException: No space left on device
ERROR: failed to solve: ResourceExhausted: ... no space left on device
You are running out of disk space. The runner will stop working when the machine runs out of disk space.

The runner’s disk is full. On standard GitHub-hosted runners that happens sooner than you’d think: GitHub documents 14 GB of SSD for them, and the root filesystem is shared with the many tools preinstalled in the image. This page shows how to see what’s using the space, then the fixes from the cheapest to the most effective.

See what is using the disk#

Add a step before the failing one (and one with if: always() after it) to see free space and the biggest directories:

.github/workflows/ci.yml
- name: Disk usage
if: always()
run: |
df -h
sudo du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -15
docker system df || true

df -h shows each filesystem. Note which one your job writes to: the workspace ($GITHUB_WORKSPACE, under /home/runner/work), Docker’s data directory (/var/lib/docker), and the temp directory ($RUNNER_TEMP) are all on the root disk by default. On Linux x64 runners a second, larger temporary disk is often mounted at /mnt: if df -h shows one, you can move heavy data there (see below). The exact sizes change with image updates, so read them from your own run.

1. Remove preinstalled tools you don’t use#

The Ubuntu image ships Android SDKs, .NET, Haskell, Swift, CodeQL bundles and several Docker images, which add up to tens of gigabytes. Deleting the ones your job doesn’t need is the quickest fix:

.github/workflows/ci.yml
- name: Free disk space
uses: jlumbroso/free-disk-space@v2
with:
android: true
dotnet: true
haskell: true
large-packages: true # apt packages such as LLVM, browsers, cloud CLIs
docker-images: true
tool-cache: false # keep setup-python/setup-node caches
swap-storage: false

Or by hand, for the biggest directories:

.github/workflows/ci.yml
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
df -h /

This step takes from a few seconds to a couple of minutes (deleting is I/O too), so keep only the directories that make a difference.

2. Use the second disk#

If /mnt has room, put the heavy data there instead of on /:

.github/workflows/ci.yml
- name: Move Docker's data to /mnt
run: |
sudo systemctl stop docker
sudo mkdir -p /mnt/docker
echo '{"data-root": "/mnt/docker"}' | sudo tee /etc/docker/daemon.json
sudo systemctl start docker
- name: Build in /mnt
run: |
sudo mkdir -p /mnt/build && sudo chown "$USER" /mnt/build
cmake -S . -B /mnt/build && cmake --build /mnt/build

maximize-build-space ↗ goes further and merges free space from both disks into one LVM volume mounted on the workspace.

3. Write less#

  • Docker builds: use a .dockerignore, multi-stage builds, and docker builder prune -af between builds in the same job. BuildKit’s own cache counts too: with cache-to: type=gha,mode=max every intermediate layer is exported, which takes space during the build. See Docker layer caching.
  • Caches and artifacts: restoring a cache unpacks it on the disk (a 5 GB compressed cache can take 15 GB). Cache less, or cache per job; see caching dependencies.
  • Matrix jobs: split a job that builds everything into a matrix of smaller ones; each gets its own disk.
  • Clean as you go: delete build directories and downloaded archives once a step no longer needs them.

4. Get a runner with a bigger disk#

When the job really needs the space, a bigger machine is the fix that doesn’t need maintenance:

  • GitHub larger runners come with 150 GB of SSD at 4 vCPUs up to 2,040 GB at 64 vCPUs, on the Team and Enterprise plans, billed per minute.
  • Self-hosted runners have whatever disk you give them. On ephemeral cloud runners, size the volume for the job and it’s thrown away afterwards.
  • RunsOn runs each job on an EC2 instance in your AWS account and takes the disk size in the job label:
.github/workflows/ci.yml
jobs:
build:
runs-on: runs-on=${{ github.run_id }}/runner=4cpu-linux-x64/volume=120gb

You can also pick an instance type with local NVMe storage (a d in the name, such as m6id or m7gd), where RunsOn puts Docker’s data directory on the fast local disk, or mount Docker on RAM with extras=tmpfs on large-memory instances. See the volume label and this tip.

Windows and macOS#

The same message appears as System.IO.IOException: There is not enough space on the disk on Windows. The Windows image is large, and the D: drive usually has more free space than C:: set your build and cache directories there. On macOS runners, df -h and removing unused Xcode versions or simulators (sudo rm -rf /Applications/Xcode_<old>.app, xcrun simctl delete unavailable) free the most space.