Troubleshooting GitLab CI Runner Jobs Stuck Pending on macOS: Registration Token & Connectivity Issues
Fix GitLab CI runner jobs stuck in pending state on macOS. This guide covers registration token errors, network connectivity, SSL, and local firewall configurations.
Fix GitLab CI runner jobs stuck in pending state on macOS. This guide covers registration token errors, network connectivity, SSL, and local firewall configurations.
When running GitLab CI/CD pipelines in a macOS local development environment, it's a common and frustrating experience to see your jobs perpetually stuck in a "Pending" state. This usually indicates that your local GitLab Runner instance is unable to register with the GitLab server or, once registered, cannot pick up new jobs. The root cause often lies in network connectivity, incorrect registration tokens, SSL certificate issues, or local macOS firewall settings preventing proper communication. This guide will walk you through a systematic troubleshooting process to resolve these persistent "Pending" job issues.
Symptom & Error Signature
You will primarily observe the following symptoms:
GitLab UI: Your CI/CD jobs, whether triggered manually or by a push, remain in a "Pending" state indefinitely, even if a runner is theoretically available and online.
(Placeholder for a screenshot showing a job stuck in pending)Runner Registration Terminal Output: When attempting to register a new runner using
gitlab-runner register, you might encounter errors indicating connection failures or inability to POST to the GitLab API.Running in system-mode. Please enter the GitLab instance URL (for example, https://gitlab.com/): https://gitlab.example.com Please enter the registration token: <YOUR_REGISTRATION_TOKEN> Please enter a description for the runner: My macOS Local Runner Please enter the tags for the runner (comma separated): macos,local Registering runner... failed runner=<TOKEN_PREFIX> status=couldn't execute POST against https://gitlab.example.com/api/v4/runners: Post "https://gitlab.example.com/api/v4/runners": dial tcp <GITLAB_IP>:443: connect: connection refused FATAL: Failed to register the runner. You may be having network problems.Or, a timeout:
Registering runner... failed runner=<TOKEN_PREFIX> status=couldn't execute POST against https://gitlab.example.com/api/v4/runners: Post "https://gitlab.example.com/api/v4/runners": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) FATAL: Failed to register the runner. You may be having network problems.Runner Logs (Running in Debug Mode): When running
gitlab-runner run --debug, you might see repetitive connection errors, SSL handshake failures, or messages indicating the runner cannot fetch new jobs.DEBU[0005] Checking for jobs... nothing runner=aBcDeFgH ERRO[0005] Failed to get the Go-GitLab client for https://gitlab.example.com/api/v4 with a timeout of 10s. error="Post "https://gitlab.example.com/api/v4/runners/verify": dial tcp <GITLAB_IP>:443: connect: operation timed out" ERRO[0005] Failed to send the runner.verify request to GitLab API, failed to verify runner. runner=aBcDeFgH status=403 Forbidden
Root Cause Analysis
The "pending stuck" issue typically stems from one or more of the following underlying problems:
Network Connectivity Issues: This is the most prevalent cause.
- Local Firewall (macOS/Third-Party): macOS's built-in firewall or third-party solutions (e.g., Little Snitch, LuLu) blocking outgoing connections from the
gitlab-runnerprocess or Docker containers to the GitLab instance. - Corporate/VPN Firewalls: If you're on a corporate network or VPN, it might restrict access to your GitLab instance's URL/IP.
- DNS Resolution: The macOS environment failing to correctly resolve the GitLab instance's hostname to an IP address.
- Proxy Configuration: Incorrect or missing proxy settings for the
gitlab-runnerprocess or Docker daemon.
- Local Firewall (macOS/Third-Party): macOS's built-in firewall or third-party solutions (e.g., Little Snitch, LuLu) blocking outgoing connections from the
Incorrect GitLab Instance URL or Registration Token:
- Typos: Simple errors in the GitLab instance URL (e.g.,
httpinstead ofhttps). - Invalid Token: The registration token copied from the GitLab UI is incorrect, expired, or belongs to a different project/group.
- Typos: Simple errors in the GitLab instance URL (e.g.,
SSL/TLS Certificate Problems:
- Self-Signed Certificates: If your GitLab instance uses a self-signed SSL certificate, the macOS environment or Docker containers might not trust it, leading to handshake failures.
- Missing CA Certificates: Intermediate CA certificates not being properly installed or recognized.
Docker Daemon and Environment Issues (if using Docker executor):
- Docker Desktop Not Running: The Docker daemon required by the runner's Docker executor is not active.
- Docker Network Problems: Internal Docker network issues preventing containers from reaching the internet or the host.
- Resource Constraints: Docker Desktop running out of memory or CPU resources.
Corrupted Runner Configuration: The
config.tomlfile might be misconfigured or corrupted, preventing the runner from starting or picking up jobs correctly.
Step-by-Step Resolution
Follow these steps systematically to diagnose and resolve your "pending stuck" GitLab CI runner jobs on macOS.
1. Verify Network Connectivity to GitLab Instance
This is the most critical first step. Ensure your macOS machine can reach your GitLab instance.
Ping Test:
ping gitlab.example.comLook for successful replies. If you see
Request timeout for icmp_seq..., there's a connectivity issue.Traceroute:
traceroute gitlab.example.comThis command helps identify where the connection is failing (e.g., at your router, a corporate firewall, or the GitLab server itself).
HTTPS Connection Test with
curl:curl -v https://gitlab.example.com/api/v4/versionLook for an HTTP 200 OK status code and version information. If you get
curl: (7) Failed to connect...orcurl: (35) SSL peer certificate or -with-long-error..., it indicates a network or SSL issue.Test from within a Docker Container (if using Docker executor):
docker run --rm alpine:latest ping -c 3 gitlab.example.com docker run --rm alpine/git curl -v https://gitlab.example.com/api/v4/versionThis confirms if the Docker environment itself has network access.
If any of these network tests fail, your runner will not be able to communicate with GitLab. Prioritize resolving network connectivity before proceeding.
2. Confirm GitLab Instance URL and Registration Token
Simple errors here are surprisingly common.
- GitLab Instance URL: Double-check the URL in your browser when accessing your GitLab. Ensure it includes
https://if your GitLab instance is secured. - Registration Token:
- Navigate to your GitLab project or group's Settings > CI/CD > Runners.
- Find the specific runner registration token (either for "Project runners" or "Group runners" depending on your setup).
- Copy the token carefully. Regenerate the token if you suspect it's been exposed or is incorrect, and then use the new one.
3. Address SSL/TLS Certificate Issues
If your GitLab instance uses a self-signed certificate or one not widely trusted, your macOS machine or Docker containers might reject the connection.
For
gitlab-runneron macOS:- Obtain the CA certificate:
openssl s_client -showcerts -connect gitlab.example.com:443 </dev/null 2>/dev/null | openssl x509 -outform PEM > gitlab.example.com.crt - Install the certificate into macOS Keychain:
Open
gitlab.example.com.crt, double-click, and add it to your keychain, trusting it for SSL. - Configure
config.toml: Edit your runner'sconfig.toml(usually located at~/.gitlab-runner/config.tomlor/etc/gitlab-runner/config.toml) and add thetls-ca-fileentry under the[[runners]]section:[[runners]] # ... other runner configuration tls-ca-file = "/path/to/your/gitlab.example.com.crt" # ...
- Obtain the CA certificate:
For Docker Executor (if
tls-ca-fileisn't enough): If jobs still fail within Docker containers, you need to ensure Docker containers trust the certificate.- Make the certificate available to Docker containers by mounting it as a volume in
config.toml:
Replace[[runners]] # ... executor = "docker" [runners.docker] # ... volumes = ["/cache", "/path/to/your/gitlab.example.com.crt:/etc/ssl/certs/gitlab.example.com.crt:ro"] # .../path/to/your/gitlab.example.com.crtwith the actual path on your macOS host. - Alternatively, for specific images, you might need to build a custom Docker image that includes your CA certificate.
- Make the certificate available to Docker containers by mounting it as a volume in
You can bypass SSL verification by setting
CI_SERVER_SKIP_VERIFY_SSL=truein theconfig.tomlunder the[runners]section or as an environment variable in your CI/CD pipeline. This is highly discouraged for production environments as it opens you to Man-in-the-Middle attacks. Use only for temporary debugging in isolated local environments.[[runners]] environment = ["CI_SERVER_SKIP_VERIFY_SSL=true"] # ...
4. Re-register the GitLab Runner
A fresh registration often resolves issues caused by corrupted configurations or outdated tokens.
Delete Existing Runner (from GitLab UI):
- Navigate to your GitLab project/group's Settings > CI/CD > Runners.
- Find your macOS runner, click the "Edit" button (pencil icon), and then click "Remove runner" at the bottom. This ensures GitLab no longer expects the old runner.
Stop and Clean Runner Configuration (on macOS):
- Stop the running
gitlab-runnerprocess:gitlab-runner stop - Delete the old configuration file.
rm -rf ~/.gitlab-runner/config.toml # For user-specific runner # OR sudo rm -rf /etc/gitlab-runner/config.toml # For system-wide runner
- Stop the running
Register the Runner Again:
- Run the registration command using the correct URL and the (potentially new) registration token. Choose your preferred executor (e.g.,
dockerorshell).
gitlab-runner register --url https://gitlab.example.com/ --registration-token <YOUR_REGISTRATION_TOKEN> --executor docker --description "macOS Local Runner" --tag-list "macos,local,docker" --docker-image "alpine:latest" --non-interactive- For a
shellexecutor:
gitlab-runner register --url https://gitlab.example.com/ --registration-token <YOUR_REGISTRATION_TOKEN> --executor shell --description "macOS Local Shell Runner" --tag-list "macos,local,shell" --non-interactive- Run the registration command using the correct URL and the (potentially new) registration token. Choose your preferred executor (e.g.,
Start the Runner:
gitlab-runner start # OR to run interactively and see logs: gitlab-runner run
Ensure the
gitlab-runnerprocess has the necessary permissions to access its configuration and execute jobs. If installed via Homebrew, it typically runs under your user context.
5. Verify Docker Daemon Status and Connectivity (if using Docker executor)
If you've configured your runner to use the docker executor, Docker Desktop must be running and healthy.
- Check Docker Desktop: Ensure Docker Desktop is running on your macOS machine.
- Check Docker Info:
Look for "Server Version" and other healthy statistics. If it fails, restart Docker Desktop.docker info - Check Docker Processes:
Confirm no unexpected issues.docker ps - Docker Network: If you suspect internal Docker network issues, try restarting Docker Desktop, or resetting Docker to factory defaults (Docker Desktop -> Settings -> Troubleshoot -> Reset to factory defaults, warning: this removes all images/containers).
6. Check macOS Firewall & Proxy Settings
macOS and third-party firewalls can silently block connections.
macOS Built-in Firewall:
- Go to
System Settings->Network->Firewall. - Ensure it's not blocking outgoing connections for
gitlab-runneror Docker. You might need to temporarily disable it for testing. - You can inspect
pfctlrules via terminal, but the GUI is usually sufficient:sudo pfctl -s rules # View current pf rules
- Go to
Third-Party Firewalls (e.g., Little Snitch, LuLu): These tools require explicit rules to allow
gitlab-runnerand Docker processes (e.g.,com.docker.backend,com.docker.hyperkit) to connect to your GitLab instance's IP address and port 443. Check their respective configuration panels and add appropriate "Allow" rules.Proxy Settings:
- Go to
System Settings->Network->(Your Active Network Interface)->Details...->Proxies. - Ensure no unintended proxy configurations are active, or if a proxy is required, ensure it's correctly configured for HTTP/HTTPS.
- If a proxy is needed, configure it in your
config.tomlunder the[runners]section or as environment variables:
And for Docker daemon itself, configure it in Docker Desktop settings.[[runners]] # ... environment = ["HTTP_PROXY=http://proxy.example.com:8080", "HTTPS_PROXY=http://proxy.example.com:8080", "NO_PROXY=localhost,127.0.0.1,gitlab.example.com"] # ...
- Go to
7. Inspect Runner Logs with Debug Mode
Running the runner in debug mode provides verbose output, which can be invaluable for pinpointing specific errors.
- Stop any running runner instances:
gitlab-runner stop - Run in foreground with debug:
Observe the output carefully. Look for specific error messages related togitlab-runner run --debugdial tcp,SSL handshake,connection refused, orcertificate verify failed. These messages will often directly point to the underlying problem.
8. Remove and Reinstall GitLab Runner (Last Resort)
If all else fails, a clean reinstallation can sometimes resolve cryptic issues.
- Uninstall via Homebrew:
brew uninstall gitlab-runner - Ensure all related files are gone:
sudo rm -rf ~/.gitlab-runner/ /etc/gitlab-runner/ /usr/local/bin/gitlab-runner - Reinstall:
brew install gitlab-runner - Then, proceed with Step 4 (Re-register the GitLab Runner).
By following these systematic steps, you should be able to diagnose and resolve the "GitLab CI runner jobs pending stuck" issue on your macOS local environment and get your CI/CD pipelines flowing smoothly again.
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.