# CircleCI Build Timeout: Complete Fix Guide
Your CircleCI build starts fine, runs for a while, and then—silence. Ten minutes later, the build fails with a timeout error. The logs show it was working on something, then just stopped.
CircleCI has strict timeout limits, and hitting them is a common issue. Let me walk through every type of timeout you'll encounter and how to fix them.
Understanding CircleCI Timeouts
CircleCI has several timeout layers:
| Timeout Type | Default Limit | Where to Set |
|---|---|---|
| Step timeout | No default (job limit applies) | no_output_timeout in config |
| Job timeout | 5 hours (Free), 70 min (Performance) | Project settings |
| Workflow timeout | No direct limit | Job composition |
| SSH timeout | 2 hours | N/A |
When a step produces no output for a period, CircleCI considers it "hung" and kills it. This is the most common timeout.
Fix 1: No Output Timeout
A command produces no output for too long:
Too long with no output received (exceeded 10m0s): context deadline exceededCause: Your command is running but not printing anything to stdout.
Solution A: Add output to long-running commands:
# config.yml
steps:
- run:
name: Build application
# Default no_output_timeout is 10 minutes
command: |
echo "Starting build..."
make build
echo "Build complete"For long-running commands:
- run:
name: Long database migration
no_output_timeout: 30m # Increase timeout
command: |
echo "Starting migration..."
python migrate.py 2>&1 | while IFS= read -r line; do
echo "$line"
done
echo "Migration complete"Solution B: Use background steps for very long processes:
```yaml - run: name: Start server background: true command: | npm start
- run:
- name: Run tests
- command: |
- npx wait-on http://localhost:3000
- npm test
`
Solution C: Add progress indicators:
- run:
name: Process large files
command: |
for file in large_files/*; do
echo "Processing $file..."
process "$file"
doneFix 2: Job Timeout Exceeded
The entire job exceeds the maximum time:
Job exceeded maximum execution time. Job timed out after 1h10m0s.Cause: Your job takes longer than the plan's limit.
Solution A: Split into multiple jobs:
Instead of one long job:
# DON'T: One long job
jobs:
build:
docker:
- image: cimg/node:20.0
steps:
- checkout
- run: npm install
- run: npm run build
- run: npm run test:unit
- run: npm run test:integration
- run: npm run test:e2e
- run: npm run deploySplit into parallel jobs:
```yaml # DO: Multiple jobs workflows: version: 2 build-test-deploy: jobs: - build - test-unit: requires: - build - test-integration: requires: - build - test-e2e: requires: - build - deploy: requires: - test-unit - test-integration - test-e2e
jobs: build: docker: - image: cimg/node:20.0 steps: - checkout - run: npm install - run: npm run build - persist_to_workspace: root: . paths: - dist
test-unit: docker: - image: cimg/node:20.0 steps: - attach_workspace: at: . - run: npm run test:unit
test-integration: docker: - image: cimg/node:20.0 steps: - attach_workspace: at: . - run: npm run test:integration
# ... etc ```
Solution B: Increase job timeout in project settings:
- 1.Go to Project Settings → Advanced Settings
- 2.Find "Maximum Build Duration"
- 3.Increase (limited by your plan)
Or in config:
jobs:
build:
max_run_time: 1h30m # Override project default
docker:
- image: cimg/node:20.0Fix 3: Resource Class Timeout
Running heavy tasks on a small resource class:
Error: Container crashed (OOMKilled)Cause: Your job needs more CPU/memory.
Solution: Upgrade resource class:
```yaml jobs: build: # Small (default): 2 CPU, 4GB RAM # Medium: 4 CPU, 8GB RAM # Medium+: 6 CPU, 12GB RAM # Large: 8 CPU, 16GB RAM # Xlarge: 16 CPU, 32GB RAM
resource_class: large # Upgrade from default docker: - image: cimg/node:20.0 ```
For resource-intensive builds:
jobs:
heavy-build:
resource_class: xlarge
docker:
- image: cimg/node:20.0
steps:
- checkout
- run: npm ci
- run: npm run build:heavyFix 4: Dependency Installation Timeout
Installing dependencies takes too long:
npm ERR! network timeout at: https://registry.npmjs.org/packageSolution A: Use caching:
```yaml steps: - restore_cache: keys: - deps-{{ checksum "package-lock.json" }} - deps-
- run: npm ci
- save_cache:
- key: deps-{{ checksum "package-lock.json" }}
- paths:
- - node_modules
`
Solution B: Increase npm timeout:
- run:
name: Install dependencies
command: npm ci --fetch-timeout=600000 # 10 minutesSolution C: Use CircleCI CI-friendly images:
docker:
# Use CircleCI's CI-optimized images
- image: cimg/node:20.0 # Has npm cache, common deps pre-installedSolution D: Split dependency installation:
```yaml - run: name: Install production dependencies command: npm ci --only=production
- run:
- name: Install dev dependencies
- command: npm ci --development
`
Fix 5: Test Suite Timeout
Test suites run too long:
Too long with no output received (exceeded 10m0s)Solution A: Run tests in parallel:
jobs:
test:
parallelism: 4 # Split tests across 4 containers
docker:
- image: cimg/node:20.0
steps:
- checkout
- run: npm ci
- run:
name: Run tests in parallel
command: |
TESTFILES=$(circleci tests glob "test/**/*.test.js" | circleci tests split --split-by=timings)
npm test $TESTFILESSolution B: Add verbose output:
- run:
name: Run tests
command: npm test -- --verbose --reporter=spec
no_output_timeout: 20mSolution C: Use test timing for splitting:
```yaml - store_test_results: path: test-results
- store_artifacts:
- path: test-results
`
CircleCI uses stored test results to optimize test splitting.
Fix 6: Docker Build Timeout
Building Docker images times out:
- run:
name: Build Docker image
command: docker build -t myapp . # Can take forever without outputSolution:
```yaml - setup_remote_docker: version: docker24 docker_layer_caching: true # Cache layers
- run:
- name: Build Docker image
- no_output_timeout: 30m
- command: |
- docker build \
- --progress=plain \ # Show build output
- -t myapp:latest \
- .
`
Use buildx for better progress:
- run:
name: Build with buildx
command: |
docker buildx create --use
docker buildx build \
--progress=plain \
-t myapp:latest \
.Fix 7: Database Migration Timeout
Database operations timeout:
- run:
name: Run migrations
command: python manage.py migrateSolution:
- run:
name: Run migrations
no_output_timeout: 20m
environment:
DB_MIGRATION_PROGRESS: "true" # If your tool supports it
command: |
echo "Starting migrations..."
python manage.py migrate --verbosity=2
echo "Migrations complete"Add progress reporting:
- run:
name: Run migrations with progress
command: |
python manage.py migrate --verbosity=2 2>&1 | while IFS= read -r line; do
echo "$line"
doneFix 8: Cache/Artifact Upload Timeout
Uploading large caches or artifacts times out:
Error: Timeout uploading cacheSolution A: Reduce cache size:
- save_cache:
key: deps-{{ checksum "package-lock.json" }}
paths:
- node_modules
# Don't cache everything
# - ~/.npm # May not need thisSolution B: Compress before uploading:
```yaml - run: name: Prepare artifacts command: | tar -czf artifacts.tar.gz build/
- store_artifacts:
- path: artifacts.tar.gz
`
Solution C: Split artifacts:
```yaml - run: name: Split large artifacts command: | mkdir -p artifacts split -b 50M large-file.tar artifacts/part-
- store_artifacts:
- path: artifacts
`
Quick Reference: Timeout Prevention
| Scenario | Fix |
|---|---|
| No output for 10m | Add no_output_timeout, add echo statements |
| Job too long | Split into parallel jobs |
| OOM killed | Upgrade resource_class |
| Slow deps | Use caching, CI-optimized images |
| Slow tests | Use parallelism, test splitting |
| Docker build slow | Enable layer caching, use progress output |
Timeout Debugging Commands
# Add at the start of your job to debug timeout issues
- run:
name: Debug environment
command: |
echo "=== System Info ==="
free -h
df -h
nproc
echo "=== Running Processes ==="
ps aux | head -20
echo "=== Network ==="
curl -I https://circleci.com 2>&1 | head -5