Fix: GitHub Actions Runner Failed to Start or Connect
Quick Answer
Fix GitHub Actions self-hosted runner failures including connection issues, version mismatches, and registration problems with step-by-step solutions.
The Error
You set up a self-hosted runner for GitHub Actions and see one of these messages:
Error: The self-hosted runner lost communication with the server.Could not resolve host: github.comRunner connect error: The HTTP request timed out after 00:01:00.Or the runner appears offline in your repository’s Settings > Actions > Runners page, even though you believe it’s running.
Why This Happens
Self-hosted runners maintain a persistent HTTPS connection to GitHub’s servers. When this connection fails, jobs queue indefinitely and the runner shows as offline. Common causes include network restrictions blocking the required endpoints, runner version incompatibility, expired registration tokens, or resource exhaustion on the runner machine.
GitHub regularly updates the runner application and may refuse connections from outdated versions. The runner also requires access to specific domains and ports that corporate firewalls or cloud security groups might block.
Fix 1: Check Network Connectivity
The runner needs outbound HTTPS access to several GitHub domains. Test connectivity from the runner machine:
curl -v https://github.com
curl -v https://api.github.com
curl -v https://codeload.github.com
curl -v https://objects.githubusercontent.comAll must return HTTP 200 or 301. If any fail, check your firewall rules. The runner communicates exclusively over HTTPS (port 443).
For runners behind a corporate proxy:
export https_proxy=http://proxy.company.com:8080
export http_proxy=http://proxy.company.com:8080
export no_proxy=localhost,127.0.0.1Add these to the runner’s .env file (located in the runner directory) to persist across restarts.
Pro Tip: GitHub publishes its IP ranges via the meta API. Use the
actionskey to find the IP ranges your firewall needs to allow.
Fix 2: Update the Runner Version
GitHub requires runners to be within a certain version range. Check your current version:
./run.sh --versionCompare it with the latest release on GitHub. If your version is more than a few minor versions behind, update:
# Stop the runner
sudo ./svc.sh stop
# Download and extract the latest version
curl -o actions-runner-linux-x64.tar.gz -L \
https://github.com/actions/runner/releases/download/v2.XXX.X/actions-runner-linux-x64-2.XXX.X.tar.gz
tar xzf actions-runner-linux-x64.tar.gz
# Restart
sudo ./svc.sh startThe runner has auto-update capability, but it sometimes fails if the runner process isn’t running when an update is published.
Fix 3: Re-register the Runner
Registration tokens expire after 1 hour. If the runner was configured with an expired token, it won’t connect. Re-register:
# Remove existing registration
./config.sh remove --token YOUR_REMOVAL_TOKEN
# Generate a new token from:
# Settings > Actions > Runners > New self-hosted runner
# Re-configure
./config.sh --url https://github.com/OWNER/REPO --token NEW_TOKENFor organization-level runners, use the organization settings page instead. You can also generate tokens via the GitHub API:
curl -X POST \
-H "Authorization: token YOUR_PAT" \
https://api.github.com/repos/OWNER/REPO/actions/runners/registration-tokenFix 4: Fix Label and Group Mismatches
Jobs target runners using labels. If your workflow specifies a label the runner doesn’t have, the job queues forever:
# Workflow expects this label
runs-on: self-hosted-gpu
# But runner was configured with
# ./config.sh --labels self-hosted,linux,x64Check runner labels in Settings > Actions > Runners. Add missing labels:
# You must remove and re-register to change labels
./config.sh remove --token TOKEN
./config.sh --url https://github.com/OWNER/REPO \
--token NEW_TOKEN \
--labels self-hosted,linux,x64,self-hosted-gpuCommon Mistake: Runner groups (enterprise/organization feature) can restrict which repositories a runner serves. If your runner is in a group that doesn’t include your repository, jobs won’t be routed to it. Check organization Settings > Actions > Runner groups.
Fix 5: Fix Docker-Based Runner Issues
If you run the GitHub Actions runner inside a Docker container, several issues can arise:
# Common mistake: running as root without --user
FROM ubuntu:22.04
# Runner refuses to run as root by defaultThe runner won’t start as root unless you set RUNNER_ALLOW_RUNASROOT=1:
docker run -e RUNNER_ALLOW_RUNASROOT=1 \
-v /var/run/docker.sock:/var/run/docker.sock \
your-runner-imageFor Docker-in-Docker workflows, mount the Docker socket:
docker run -v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp:/tmp \
your-runner-imageMake sure the runner container has enough disk space for workspace files and Docker layer caching.
Fix 6: Address Resource Limits
The runner may crash or hang if the machine runs out of resources. Check:
# Memory
free -h
# Disk space
df -h
# CPU
top -bn1 | head -5
# Check if runner process is alive
ps aux | grep Runner.ListenerCommon resource issues:
- Disk full: Old workflow artifacts and Docker images accumulate. Clean up with
docker system prune -afand clear the runner’s_workdirectory. - Memory exhaustion: The runner itself uses ~200MB, but your workflows may need much more. Monitor with
dmesg | grep -i oomto check for OOM kills. - Too many concurrent jobs: By default, a runner processes one job at a time. Running multiple runners on the same machine requires enough resources for all concurrent jobs.
Fix 7: Fix GITHUB_TOKEN Permissions
The runner uses a GITHUB_TOKEN that’s automatically generated for each workflow run. If permissions are too restrictive, steps that interact with the repository may fail:
permissions:
contents: read
packages: write
issues: writeFor organization repositories with restrictive default permissions, set permissions explicitly in your workflow:
jobs:
build:
runs-on: self-hosted
permissions:
contents: write
pull-requests: writeCheck your organization settings under Settings > Actions > General > Workflow permissions. “Read repository contents” is the most restrictive default and may block operations like pushing commits or creating releases.
Fix 8: Debug Using Runner Logs
The runner writes detailed logs that reveal exactly why it can’t connect:
# Service logs (if installed as service)
journalctl -u actions.runner.OWNER-REPO.RUNNER_NAME -f
# Or check the log files directly
cat _diag/Runner_*.log | tail -100
cat _diag/Worker_*.log | tail -100Look for these key messages:
"Authentication failed"— Token expired or invalid. Re-register."Http response code: Unauthorized"— PAT or app token lacks required scopes."Connect timeout"— Network issue. Check firewall and DNS."Version not supported"— Runner too old. Update."No free disk space"— Clean up the_workdirectory.
Enable diagnostic logging by creating a .env file in the runner directory:
ACTIONS_RUNNER_DEBUG=true
ACTIONS_STEP_DEBUG=trueStill Not Working?
Check if GitHub is down. Visit githubstatus.com before deep-diving into your configuration.
Verify DNS resolution. Run
nslookup github.comfrom the runner machine. Corporate DNS servers sometimes block or redirect GitHub domains.Check TLS certificates. Corporate proxies that perform SSL inspection can break the runner’s HTTPS connection. Add your corporate CA certificate to the runner’s trust store.
Try running interactively. Stop the service and run
./run.shdirectly. This shows real-time errors that the service logs might not capture.Check Docker image compatibility. If using a container-based runner, ensure the base image has all required dependencies (
libicu,libssl,git).Monitor the runner process. Use
systemctl status actions.runner.*to check if the service is actually running or if it crashed silently.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Git remote rejected — file exceeds GitHub's file size limit of 100.00 MB
Resolve the GitHub push error when a file exceeds the 100 MB size limit by removing the large file from history, using Git LFS, or cleaning your repository with BFG Repo Cleaner.
Fix: ASP.NET 500 Internal Server Error
Fix ASP.NET 500 Internal Server Error by enabling developer exception pages, fixing DI registration, connection strings, and middleware configuration.
Fix: Celery Task Not Received or Not Executing
Fix Celery tasks not being received or executed by resolving broker connections, autodiscovery issues, task name mismatches, and worker configuration.
Fix: Elasticsearch Cluster Health Red Status
Fix Elasticsearch cluster health red status by resolving unassigned shards, disk watermark issues, node failures, and shard allocation problems.