actions / actions/runner

GitHub Actions self-hosted runner should handle system clock skew gracefully instead of exiting permanently

Open
#4,648 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C#
Stars
6.3k
Forks
1.4k
Avg merge
1d 16h
Merged PRs (30d)
24

Description

Summary

A self-hosted GitHub Actions runner can fail during boot if the machine's system clock has not yet synchronized.

When this happens, GitHub rejects the runner's OAuth token because the local clock is significantly behind the GitHub server time. However, the runner reports:

Failed to create a session. The runner registration has been deleted from the server, please re-configure.
Runner registrations are automatically deleted for runners that have not connected to the service recently.

This message is misleading because the runner registration has not actually been deleted.

More importantly, the runner exits and does not retry after the system clock becomes synchronized. Since the systemd service then remains inactive, the self-hosted runner stays offline until manually restarted.

Environment

  • Self-hosted GitHub Actions runner
  • Runner version: 2.336.0
  • Linux / Raspberry Pi
  • Runner installed using svc.sh
  • systemd
  • systemd-timesyncd
  • Runner service enabled at boot

What happened

The runner service started correctly during boot:

Aug 24 15:10:40 systemd[1]: Started GitHub Actions Runner

The runner successfully reached GitHub:

√ Connected to GitHub

But session creation failed:

POST request to https://tokenghub.actions.githubusercontent.com/... failed.
HTTP Status: BadRequest

The underlying exception contained the actual cause:

GitHub.Services.OAuth.VssOAuthTokenRequestException:
The token expired on 08/24/2026 19:15:44.
Current server time is 08/25/2026 01:44:14.

The system clock was several hours behind because NTP synchronization had not completed yet.

The runner then converted this into:

Failed to create a session. The runner registration has been deleted from the server, please re-configure.

and exited:

Runner listener exited with error code 1
Runner listener exit with terminated error, stop the service, no retry needed.

Several hours later, after NTP synchronized the system clock, simply running:

sudo ./svc.sh start

caused the same runner registration to connect successfully:

√ Connected to GitHub
Current runner version: '2.336.0'
Listening for Jobs

No re-registration or configuration change was required.

Expected behavior

The runner should ideally detect this situation and handle it gracefully.

For example:

  1. If OAuth authentication fails because a token appears expired but the server time differs significantly from the local clock, report a clock-skew-specific error.
  2. Retry session creation for some period instead of permanently terminating the runner service.
  3. Avoid reporting that the runner registration has been deleted unless the server has actually confirmed that condition.

A message such as:

Authentication failed because the system clock appears to differ significantly from GitHub server time.
Check NTP/time synchronization. Retrying...

would make the actual problem much easier to diagnose.

Current workaround

I added the following systemd dependency to prevent the runner from starting before time synchronization:

[Unit]
Wants=network-online.target systemd-time-wait-sync.service
After=network-online.target systemd-time-wait-sync.service

This prevents the issue on systems using systemd-timesyncd, but it is platform-specific and shouldn't be necessary for the runner to recover from temporary clock skew.

Suggested improvement

The runner does not necessarily need to manage system time itself.

However, session/authentication failures caused by clock skew should be treated as potentially transient.

In particular, the runner could:

  • distinguish clock-skew/token-time errors from deleted runner registrations;
  • retry authentication with exponential backoff;
  • log the local and GitHub server time when a significant discrepancy is detected;
  • remain running so that it can reconnect once NTP corrects the clock.

This would make self-hosted runners much more resilient after reboots, power loss, RTC issues, or delayed NTP synchronization.

github-runner-clock-skew-report.txt

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the runner listener's session-creation path and the OAuth failure described in the issue; the reported exit code 1 shows where the service stops. Reproduce the boot-time clock-skew case or add focused coverage for it. Done means clock-skew failures are distinguishable from deleted registrations and the runner remains able to reconnect after time synchronization.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, github-actions, linux
Domain
ci-cd, devops, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.