## TL;DR
Runner registration failures are token-scope problems far more often than network problems: the token belongs to the wrong level (instance, group, or project) or has been rotated. Get a fresh token from the right settings page (Admin for instance runners, group or project Settings then CI/CD then Runners), and register with the matching scope. A token from the wrong level fails with an unhelpful generic error.

## Error / query
```text
how to debug GitLab runner registration token errors
```

## Use this skill when
- `gitlab-runner register` fails with a token error
- A runner registers but never contacts GitLab
- Registration worked before and suddenly broke
- You are unsure which token a runner needs

## Not for this skill when
- Jobs fail after the runner is registered (executor problem)
- The runner binary will not install (installation problem)
- GitLab itself is down or unreachable (server problem)

## Steps

### Step 1: Get the token from the correct level
```bash
# instance runners: Admin area, then Runners
# group runners: group Settings, then CI/CD, then Runners
# project runners: project Settings, then CI/CD, then Runners
```
Expected: a registration token (or registration flow) for exactly the scope the runner should serve. Instance tokens register shared runners; project tokens register project-only runners. Mixing levels is the top cause of failures.

### Step 2: Register non-interactively with explicit scope
```bash
gitlab-runner register --non-interactive --url "https://YOUR-gitlab-host/" --registration-token "[token-value]" --executor "docker" --docker-image "alpine:latest" --description "[runner-name]" --tag-list "[tags]" --run-untagged="false"
```
Expected: `Runner registered successfully`. The `--url` must match the GitLab external URL exactly (scheme, host, port); a mismatch here produces token-looking errors.

### Step 3: Verify the runner checks in
```bash
gitlab-runner verify
# and in GitLab: Settings, then CI/CD, then Runners, look for a green dot
```
Expected: the runner shows as active with a recent contact time. `verify` confirms the stored token still authenticates; if it fails after a success, the token was rotated or revoked.

### Step 4: Handle rotated or revoked tokens
```bash
gitlab-runner unregister --name "[runner-name]"
# then re-run the register command from step 2 with the new token
```
Expected: clean re-registration. Tokens rotate on GitLab upgrades and admin actions; when many runners fail at once, rotation (not individual runner breakage) is the cause. Re-register rather than debugging each runner's config.

## Variant phrasings

### "gitlab runner invalid registration token"
Steps 1-2. Nine times out of ten the token came from the wrong scope level.

### "gitlab-runner register fails"
Check the URL (step 2) and token scope (step 1) before anything else.

## Why it happens
GitLab has three token scopes that look identical but are not interchangeable, and the registration error does not say which scope it expected. Add token rotation on upgrades and admin resets, plus URL mismatches that surface as auth failures, and registration becomes the most failure-prone five minutes of runner setup.

## Edge cases and pitfalls
- Newer GitLab versions moved toward runner creation workflows with authentication tokens instead of shared registration tokens; check your version's docs.
- A runner behind a proxy needs `HTTP_PROXY` set for the register call too, not just for jobs.
- `--run-untagged="false"` with no matching tags means the runner idles forever; that looks like a registration problem but is a tag problem.
- config.toml from a previous registration can shadow new values; unregister fully before re-registering.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_ywpvguejWBVSjcgYCZWyag
