Resolving GitHub Actions ‘Runner Out of Disk Space’ Error on Ubuntu 20.04 LTS
Troubleshoot and fix GitHub Actions 'out of disk space' errors on Ubuntu 20.04 LTS runners. Learn to free up cache, temporary files, and optimize your CI/CD workflows for reliable builds.
Troubleshoot and fix GitHub Actions 'out of disk space' errors on Ubuntu 20.04 LTS runners. Learn to free up cache, temporary files, and optimize your CI/CD workflows for reliable builds.
Introduction
Encountering a "No space left on device" or "out of disk space" error during a GitHub Actions workflow can be a frustrating roadblock in your CI/CD pipeline. This error indicates that the virtual machine (VM) runner provisioned by GitHub for your build or deployment job has exhausted its available disk storage. On ubuntu-20.04 runners, which typically provide a finite amount of disk space (often around 75GB total, but much of it pre-populated with tools), large repositories, extensive dependencies, or accumulating build artifacts can quickly fill up the root filesystem, leading to abrupt job failures.
This guide provides a highly technical, step-by-step approach to diagnose and resolve disk space issues in your GitHub Actions workflows running on Ubuntu 20.04 LTS.
Symptom & Error Signature
When your GitHub Actions workflow runs out of disk space, you will typically see error messages in the job logs that explicitly mention storage limitations. These can manifest during various operations, such as cloning repositories, installing dependencies, compiling code, or building Docker images.
Here are common error signatures you might encounter:
Run <your build or install command>
/usr/bin/docker-credential-helper-linux: No space left on device
##[error]The process '/usr/bin/docker' failed with exit code 1
##[error]There was an error when trying to connect to the Docker daemon: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Another example during dependency installation:
mkdir: cannot create directory β/home/runner/work/my-repo/my-repo/node_modulesβ: No space left on device
Error: Command failed with exit code 1: npm install
Or during package management operations:
E: <some_package_name>: Disk space running low
E: You don't have enough free space in /var/cache/apt/archives/.
Often, diagnostic steps may reveal the full disk:
df -h
Filesystem Size Used Avail Use% Mounted on
overlay 75G 75G 0 100% /
tmpfs 64M 0 64M 0% /dev
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
shm 64M 12K 64M 1% /dev/shm
/dev/sda1 75G 75G 0 100% /etc/hosts
tmpfs 7.8G 12K 7.8G 1% /run/docker/libcontainerd/containerd/afae2...
Root Cause Analysis
The underlying reasons for GitHub Actions runners running out of disk space are typically one or a combination of the following:
- Accumulation of Large Dependencies: Projects with extensive dependency trees (e.g.,
node_modulesin Node.js, large Python virtual environments, extensive Maven or Gradle caches, Go modules) can quickly consume gigabytes of space. - Unmanaged Build Artifacts: Intermediate build products, compiler outputs, temporary files generated during compilation, or test reports that are not explicitly cleaned up can accumulate.
- Docker Image Bloat: Building Docker images, especially without proper multi-stage builds or pruning strategies, can leave numerous intermediate layers and unused images (
danglingornone) consuming significant space. Eachdocker buildcommand creates new layers. - Inefficient Caching: While
actions/cacheis designed to save space and time, misconfigured keys or excessively large cached items can sometimes contribute to the problem, or simply the cache not being utilized for large dependency sets. - GitHub-Hosted Runner Limitations: The default GitHub-hosted runners (like
ubuntu-20.04) have a fixed amount of disk space. While generous for most projects, very large or complex builds may exceed these limits. The filesystem is anoverlayfson top of a base image, often with/dev/sda1being the underlying device providing the capacity. - Tooling and Environment Bloat: GitHub Actions runners come pre-installed with a vast array of tools. While optimized, some workflows might inadvertently duplicate or update these, or generate temporary files that aren't cleaned.
Step-by-Step Resolution
To resolve disk space issues, you need to systematically identify what's consuming space and implement strategies to clean up or prevent accumulation.
1. Diagnose Disk Usage During Workflow Execution
The first step is to pinpoint where the space is being consumed. Add diagnostic steps to your workflow before the failing job or critical operations.
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check initial disk space
run: |
echo "Initial disk space:"
df -h
echo "Top 20 largest directories in workspace:"
sudo du -h --max-depth=1 /home/runner/work | sort -rh | head -n 20
echo "Top 20 largest directories in /usr:"
sudo du -h --max-depth=1 /usr | sort -rh | head -n 20
echo "Top 20 largest directories in /var:"
sudo du -h --max-depth=1 /var | sort -rh | head -n 20
shell: bash
# Your build steps follow here
# ...
This diagnostic output will be visible in your workflow logs and help you understand which directories (/home/runner/work, /usr, /var, etc.) are consuming the most space, guiding your cleanup efforts.
2. Implement Aggressive Cleanup of Temporary Files and Caches
Target common locations for temporary files and caches. This should ideally be done before critical operations or as a separate cleanup job.
- name: Perform System-Wide Cleanup
run: |
echo "Cleaning up APT caches..."
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
echo "Cleaning up temporary directories..."
sudo rm -rf /tmp/*
echo "Removing common tooling caches/installs (if not needed for this workflow)..."
# These directories are common large installations on GitHub runners.
# REMOVE ONLY IF YOU ARE CERTAIN THEY ARE NOT NEEDED LATER IN THE JOB.
# For example, if your project is pure Node.js, you might not need .NET or Android SDKs.
sudo rm -rf /usr/share/dotnet # .NET SDKs
sudo rm -rf /usr/local/lib/android # Android SDKs
sudo rm -rf /opt/ghc # Haskell GHC
sudo rm -rf "$AGENT_TOOLSDIRECTORY" # GitHub Actions agent tools directory
echo "Disk space after system cleanup:"
df -h
shell: bash
- name: Clean project-specific caches and dependencies
if: always() # Ensure this always runs, even if earlier steps fail
run: |
echo "Cleaning Node.js caches and modules..."
npm cache clean --force || true
rm -rf node_modules || true
yarn cache clean --force || true
echo "Cleaning Python caches and virtual environments..."
pip cache purge || true
rm -rf .venv venv || true # Remove common Python virtual environment directories
echo "Cleaning Java/Maven local repository..."
rm -rf ~/.m2/repository || true
echo "Cleaning Go module cache..."
go clean -modcache || true
echo "Disk space after project cleanup:"
df -h
shell: bash
The
|| truesuffix in cleanup commands prevents the workflow from failing if the specified files or directories do not exist. This ensures cleanup steps don't introduce new failures.Removing pre-installed tools like
/usr/share/dotnetshould only be done if you are absolutely certain your workflow does not depend on them. Misuse can lead to other build failures.
3. Optimize Docker Builds and Prune Docker Artifacts
Docker builds are a common culprit for disk space issues due to intermediate layers and unused images.
- name: Free up Docker disk space
# Run this before any Docker build steps or after they complete
run: |
echo "Pruning Docker system..."
# docker system prune --all removes all stopped containers, all networks not used by at least one container,
# all dangling images, and all build cache.
# --volumes removes all unused volumes.
sudo docker system prune --all --force --volumes
echo "Disk space after Docker prune:"
df -h
shell: bash
- name: Build and Push Docker Image
run: |
# Your docker build command
# Example using BuildKit for better caching
DOCKER_BUILDKIT=1 docker build --cache-from your-repo/your-image:latest -t your-repo/your-image:latest .
shell: bash
docker system prune --all --force --volumesis an aggressive cleanup. While generally safe in GitHub Actions runners (which are ephemeral), ensure it doesn't remove anything critical if your workflow structure relies on specific Docker artifacts persisting across sequential steps within the same job. For a fresh job, it's highly recommended.
To prevent bloat during the build:
- Use
.dockerignore: Exclude unnecessary files (likenode_modules,.git, temporary build directories) from your Docker build context. - Multi-stage builds: Reduce the size of your final Docker image by separating build-time dependencies from runtime dependencies.
- Leverage BuildKit caching: Set
DOCKER_BUILDKIT=1and use--cache-fromto reuse layers from previous builds, reducing re-downloading and re-building.
4. Effective Use of GitHub Actions Caching (actions/cache)
Properly caching dependencies is crucial for performance and can indirectly help with disk space by reducing repeated downloads, though the cache itself consumes space.
- name: Cache Node.js modules
uses: actions/cache@v4
with:
path: ~/.npm # Or ./node_modules, depending on your caching strategy
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install Node.js dependencies
run: npm ci
- name: Cache Python dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip # Or a specific venv directory
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install Python dependencies
run: pip install -r requirements.txt
Choose your
pathwisely. Cachingnode_modulesdirectly can be large. Caching the npm cache directory (~/.npm) might be more efficient for some projects. Thekeymust accurately reflect changes in your dependency lock files to ensure cache invalidation when dependencies change.
5. Split Workflows or Jobs for Large Projects
If a single job performs too many operations or generates too many artifacts, consider splitting it into multiple jobs or even separate workflows. Each job in GitHub Actions runs on a fresh VM runner, ensuring a clean slate and separate disk space.
jobs:
build_and_test:
runs-on: ubuntu-20.04
steps:
# ... build and test code ...
- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
name: my-app-build
path: ./dist # Or your build output directory
deploy:
runs-on: ubuntu-20.04
needs: build_and_test # This job will only run if build_and_test succeeds
steps:
- name: Download Build Artifacts
uses: actions/download-artifact@v4
with:
name: my-app-build
path: ./downloaded-build
# ... deploy code using artifacts ...
This approach ensures that the disk space used by the build_and_test job is entirely discarded before the deploy job starts, preventing cumulative disk usage.
6. Utilize Larger Runners (GitHub Enterprise Cloud or Self-Hosted)
If all optimization efforts prove insufficient for GitHub-hosted runners, consider these options:
Larger GitHub-Hosted Runners (Enterprise Cloud): For GitHub Enterprise Cloud customers, larger runners are available (e.g.,
ubuntu-latest-4-core,ubuntu-latest-8-core,ubuntu-latest-16-core). These offer more CPU, memory, and crucially, more disk space.jobs: build: runs-on: ubuntu-latest-4-core # Requires GitHub Enterprise Cloud steps: # ...Self-Hosted Runners: For ultimate control over resources, including disk space, deploy your own self-hosted runners. You provision and manage the underlying infrastructure (VMs or physical servers) which can have virtually unlimited disk space.
jobs: build: runs-on: self-hosted # Requires a self-hosted runner configured with this label steps: # ...Using larger GitHub-hosted runners incurs additional costs. Evaluate this option carefully against the cost-effectiveness of optimizing your existing workflows. Self-hosted runners require significant operational overhead for maintenance, security, and scaling. Ensure your self-hosted runner machines have ample disk space and implement regular cleanup routines on them if artifacts are persistently stored.
Our Production Verification Guarantee
Encountering a bug not covered here or running a non-standard kernel configuration? Our solutions are continually refined against real production incidents. Submit an environment trace for our editorial team to replicate.