ARC authentication "401 Bad credentials" in CI
GitHub rejected the credential with HTTP 401 before any permission check. For ARC this almost always means the App private key or IDs in githubConfigSecret are wrong, or the PAT is expired or revoked.
What this error means
The controller or listener logs "401 Bad credentials" or "could not refresh token". Nothing registers because authentication fails at the transport level.
ERROR could not create registration token
{"error": "POST https://api.github.com/app/installations/12345/access_tokens:
401 Bad credentials []"}Common causes
Malformed or wrong App private key
The PEM in the secret was truncated, double base64 encoded, or belongs to a different App, so token exchange returns 401.
Expired or revoked PAT
If you authenticate with a PAT rather than an App, an expired or revoked token yields 401 Bad credentials on every call.
How to fix it
Recreate githubConfigSecret from the raw values
- Download a fresh private key PEM from the App settings.
- Recreate the secret with the App ID, installation ID, and the PEM file directly.
- Restart the controller so it reloads the secret.
kubectl create secret generic pre-defined-secret \
--namespace arc-runners \
--from-literal=github_app_id=123456 \
--from-literal=github_app_installation_id=7891011 \
--from-file=github_app_private_key=./app.private-key.pemRotate an expired PAT
If using github_token, generate a new PAT with the runner admin scope and update the secret, then restart the controller.
How to prevent it
- Store the private key as a file, never hand-edited, to avoid truncation.
- Prefer a GitHub App so credentials do not expire like PATs.
- Alert on 401 in controller logs so a rotated key is caught early.