GITHUB_TOKEN and default-branch context on scheduled runs in CI
A scheduled run always executes with the default branch checked out and uses the repository default GITHUB_TOKEN permissions. github.ref is the default branch, so steps expecting a PR or feature-branch context behave differently under a cron.
What this error means
A step that worked on push fails on the schedule because github.ref is refs/heads/main, the checked-out SHA is default-branch HEAD, or a token permission the push flow had is missing.
# On schedule:
github.ref = refs/heads/main
github.sha = <default-branch HEAD>
github.event_name = schedule
# A step that read github.head_ref (PR-only) is now empty.Common causes
Schedule uses the default branch ref
The cron checks out the default branch, so github.ref and github.sha point there, not at any feature branch.
Default token permissions apply
Scheduled runs get the repository default GITHUB_TOKEN scope; if a job needs write, you must grant it with permissions.
How to fix it
Set explicit permissions for the scheduled job
- Declare the exact
permissionsthe scheduled job needs. - Avoid relying on PR-only context values under a schedule.
- Check
github.event_name == 'schedule'where behavior must differ.
permissions:
contents: read
issues: write # e.g. for a scheduled stale-issue jobBranch behavior on the event name
Use the event name to switch logic so a cron does not run PR-only steps that assume head_ref.
- if: github.event_name == 'schedule'
run: echo "scheduled path on default branch"How to prevent it
- Grant least-privilege
permissionsexplicitly for cron jobs. - Do not rely on PR-only context under a schedule.
- Test scheduled logic with workflow_dispatch on the default branch.