Common GitLab Issues

A practical reference for the GitLab issues that come up most often. From runner failures and YAML syntax errors to permission problems and registry access, understand the cause and apply the fix.

Runner Fixes GitLab
How to Use This Reference

Most GitLab issues fall into a small number of categories: runner problems, YAML configuration errors, permission and access issues, cache and registry problems, and pipeline behavior that doesn't match expectations. Each category has a set of common causes and a set of fixes. Knowing the category narrows the search dramatically — a "job stuck pending" is almost always a runner availability problem, not a YAML problem.

The issues in this reference are the ones that appear most often in GitLab support tickets and community forums. Each entry describes the symptom (what you see), the likely cause (why it happens), and the fix (how to resolve it). Some issues have multiple possible causes; the fix section lists them in order of likelihood. Start with the most common cause and work down.

The most important diagnostic tool is the job log. Every issue leaves traces in the log — the error message, the command that failed, the exit code, the environment. Before applying a fix from this reference, read the log. It often contains the answer directly. If the log doesn't explain the issue, the debugging tools (CI Lint, debug trace, variable verification) narrow it down .

Core Principle: Read the error message first. Most issues have a clear error — the challenge is interpreting it, not finding it.

Runner Issues

Jobs pending, stuck, or failing with runner-related errors. Usually availability, tags, or permissions.

YAML Issues

Syntax errors, invalid keywords, indentation problems. Caught by CI Lint before commit.

Permission Issues

401/403 errors, access denied, protected variables not available. Usually role or scope.

Cache Issues

Cache not hitting, stale cache, cache corruption. Usually key, policy, or path.

Registry Issues

Cannot push/pull images, authentication fails, storage full. Usually credentials or registry state.

Pipeline Issues

Duplicates, jobs missing, pipeline not running. Usually rules or workflow:rules.
Runner Issues

Runner issues are the most common category of GitLab CI problems. A job that stays in "pending" state isn't failing — it's waiting for a runner that matches its requirements. The requirements are the runner's tags (jobs are assigned to runners with matching tags), the runner's scope (shared, group, or project), and the runner's availability (is it paused, offline, or at capacity?). If no runner matches, the job waits indefinitely .

The "job stuck pending" issue is almost always one of these. Check the job's tags against the runner tags. Check whether the runner is shared (available to all projects) or specific (available only to its project or group). Check whether the runner is online and not paused. If the runner is online but not picking up the job, check whether it's at capacity — a runner can run only one job at a time by default, so a second job waits until the first finishes .

Runner failures with "exit code 137" or "Killed" usually indicate the job exceeded the runner's memory limit. The runner (or the underlying executor) kills the process. The fix is to reduce the job's memory usage, increase the runner's memory, or split the job into smaller pieces. For Docker executors, the limit is set in the runner's config.toml under memory and memory_swap.

# Issue: Job stuck "pending" # Causes: # - No runner matches job tags # - Runner is paused or offline # - Runner is at capacity # - Runner is not assigned to the project # Fix: # - Check job tags: CI/CD > Pipelines > (job) > Tags # - Check runner tags: Settings > CI/CD > Runners # - Ensure at least one runner has all job tags # - Check runner status (online, paused) # - Scale runner capacity if needed # Issue: "This job is stuck because you don't have any active runners" # Cause: No runners available for this project # Fix: # - Register a runner for the project # - Or enable shared runners for the project # - Settings > CI/CD > Runners > Shared runners # Issue: "no matching runner found" # Cause: Job tags don't match any runner # Fix: # - Remove job tags (use any runner) # - Or add a runner with the required tags # Issue: Job killed (exit code 137) # Cause: OOM (out of memory) # Fix: # - Reduce job memory usage # - Increase runner memory in config.toml # - Split job into smaller pieces # Issue: "Failed to pull image" # Cause: Runner cannot pull the image # Fix: # - Check image name/tag # - Check registry credentials # - Check runner network access # - For private registry: add image pull secret # Debug runner status: # Settings > CI/CD > Runners # Check: online status, tags, paused state # Or via API: GET /projects/:id/runners
Runner Debugging Checklist:
  • Is the runner online? (Settings > CI/CD > Runners)
  • Is it paused? (paused runners don't accept jobs)
  • Does it have the job's tags? (tags must match exactly)
  • Is it shared or specific? (shared runners serve all projects)
  • Is it at capacity? (one job at a time by default)
  • Does it have network access to the registry? (for image pulls)
YAML and Configuration Issues

YAML syntax errors are the most common configuration issue, and the most preventable. YAML is indentation-sensitive: a single misaligned space breaks the structure. Tabs are not allowed — YAML requires spaces. Keys must be followed by a colon and a space. Strings with special characters (colons, hashes, brackets) must be quoted. These rules are simple but easy to violate, especially when copying configuration from documentation .

The CI Lint tool catches most syntax errors before commit. It validates the YAML structure and the GitLab CI schema, reporting the line number and a description of the problem. The pipeline editor provides live validation as you type. Both are faster than pushing a commit and waiting for a pipeline to fail. If you're editing a large file, validate after every few changes — small errors are easier to find than accumulated ones.

Beyond syntax, configuration logic errors can cause pipelines to behave unexpectedly. A job with a rules clause that never matches won't run. A needs reference to a job that doesn't exist fails validation. A workflow:rules that evaluates to never blocks the entire pipeline. The pipeline editor's "Validate" tab simulates pipeline creation, catching these logic errors that syntax validation misses .

# Issue: YAML invalid # Causes: # - Tabs instead of spaces # - Inconsistent indentation # - Missing space after colon # - Unquoted special characters # - Duplicate keys # Fix: # - Use CI Lint to identify the error # - Check indentation (2 spaces consistently) # - Quote strings with special characters # - Remove duplicate keys # Issue: "jobs config should contain at least one visible job" # Cause: All jobs are hidden (start with .) or excluded by rules # Fix: # - Add at least one visible job # - Or fix the rules that exclude all jobs # Issue: "unknown keys in the YAML" # Cause: Invalid keyword (typo, deprecated, or wrong level) # Fix: # - Check the keyword in GitLab CI/CD reference # - Fix spelling # - Move to correct level (global vs job) # Issue: "This GitLab CI configuration is invalid" # Cause: Various — schema violation # Fix: # - Read the error message for the specific problem # - Check the line number # - Use the pipeline editor to see the error inline # Issue: "config contains unknown keys: only" # Cause: only/except was removed in GitLab 18 # Fix: # - Replace only/except with rules # - Example: # rules: # - if: $CI_COMMIT_BRANCH == "main" # Issue: BOM in .gitlab-ci.yml # Cause: Editor inserts UTF-8 BOM # Fix: # - Check: hexdump -C .gitlab-ci.yml | head -1 # - If starts with ef bb bf, remove BOM # - Use an editor that doesn't insert BOM # Issue: Included file not found # Cause: Wrong path, wrong ref, or file doesn't exist # Fix: # - Check path format (starts with /) # - Check ref exists # - Check file exists in that ref # Validate with CI Lint: # Build > CI Lint > Paste YAML > Validate
YAML Best Practices: