Checks
Controller Version
0.14.2
Deployment Method
ArgoCD
Checks
To Reproduce
- Deploy
gha-runner-scale-set-controller and gha-runner-scale-set 0.14.2 with --update-strategy=eventual, minRunners: 1, and maxRunners: 10.
- Wait until the
AutoscalingRunnerSet, AutoscalingListener, and EphemeralRunnerSet are healthy.
- Change
AutoscalingRunnerSet.spec.template.spec so ARC rolls the EphemeralRunnerSet. In our case, a GitOps deployment removed an obsolete runtimeClassName and changed the runner container security context.
- Observe that the old EphemeralRunnerSet is deleted and a different EphemeralRunnerSet survives, while
AutoscalingListener.spec.ephemeralRunnerSetName still names the deleted set.
- The controller repeatedly recreates the listener pod from that unchanged
AutoscalingListener. Every pod attempts its initial patch against the deleted EphemeralRunnerSet, exits, and enters a permanent recreate/crash loop.
This happened during an update to an existing scale set, rather than a fresh install.
Describe the bug
On ARC 0.14.2, an AutoscalingListener remained bound to a deleted EphemeralRunnerSet after a runner-template update. The surviving EphemeralRunnerSet had a different generated name, but the listener CR, config, and RBAC still referenced the deleted name.
Every listener restart failed identically:
Application returned an error: handling initial message failed: could not patch ephemeral runner set,
patch JSON: {"spec":{"patchID":0,"replicas":1}},
error: ephemeralrunnersets.actions.github.com "<scale-set>-qb49n" not found
The controller then deleted and recreated the listener pod, but did not repair or replace the stale AutoscalingListener CR, so the loop continued indefinitely and jobs could not be assigned.
The symptoms and stale-reference mechanism match #4489 very closely. That issue covered 0.14.0/0.14.1 fresh installs and was closed by stale automation without a linked fix. This report confirms the same failure on 0.14.2 and during an update to an existing AutoscalingRunnerSet.
Recovery/workaround:
- Detect that
AutoscalingListener.spec.ephemeralRunnerSetName is not the single active EphemeralRunnerSet.
- Delete the stale AutoscalingListener CR.
- With
updateStrategy=eventual, ARC drains running jobs, creates the replacement EphemeralRunnerSet/listener, and recovers.
We currently run that check as a post-sync hook because the controller did not self-heal the stale reference.
Describe the expected behavior
After replacing an EphemeralRunnerSet, ARC should atomically create/update the listener against the surviving set, or reconcile and replace any listener whose spec.ephemeralRunnerSetName points to a missing/non-current set.
A listener pod restart should not repeatedly inherit a permanently stale generated resource name.
Additional Context
controllerVersion: 0.14.2
scaleSetChartVersion: 0.14.2
kubernetesVersion: v1.35.2
controllerArgs:
- --auto-scaling-runner-set-only
- --watch-single-namespace=<runner-namespace>
- --runner-max-concurrent-reconciles=2
- --update-strategy=eventual
scaleSet:
minRunners: 1
maxRunners: 10
observedState:
listenerTarget: <scale-set>-qb49n
listenerTargetExists: false
activeEphemeralRunnerSet: <different generated name>
relatedIssues:
- https://github.com/actions/actions-runner-controller/issues/4489
- https://github.com/actions/actions-runner-controller/issues/4432
Controller Logs
Complete captured controller log window (the controller includes the terminated listener's full output in message):
https://gist.github.com/DocX/80b533f37c0bd1a5253fdd8514df6609
The first entry already contains the decisive listener error; the recreate loop continues throughout the capture.
Runner Pod Logs
No runner pod failure was involved. The failing pod was the AutoscalingListener, and its complete output is embedded in the controller termination messages in the gist above. Runner creation/assignment was blocked because the listener could not patch its referenced EphemeralRunnerSet.
Checks
Controller Version
0.14.2
Deployment Method
ArgoCD
Checks
To Reproduce
gha-runner-scale-set-controllerandgha-runner-scale-set0.14.2 with--update-strategy=eventual,minRunners: 1, andmaxRunners: 10.AutoscalingRunnerSet,AutoscalingListener, andEphemeralRunnerSetare healthy.AutoscalingRunnerSet.spec.template.specso ARC rolls the EphemeralRunnerSet. In our case, a GitOps deployment removed an obsoleteruntimeClassNameand changed the runner container security context.AutoscalingListener.spec.ephemeralRunnerSetNamestill names the deleted set.AutoscalingListener. Every pod attempts its initial patch against the deleted EphemeralRunnerSet, exits, and enters a permanent recreate/crash loop.This happened during an update to an existing scale set, rather than a fresh install.
Describe the bug
On ARC 0.14.2, an AutoscalingListener remained bound to a deleted EphemeralRunnerSet after a runner-template update. The surviving EphemeralRunnerSet had a different generated name, but the listener CR, config, and RBAC still referenced the deleted name.
Every listener restart failed identically:
The controller then deleted and recreated the listener pod, but did not repair or replace the stale AutoscalingListener CR, so the loop continued indefinitely and jobs could not be assigned.
The symptoms and stale-reference mechanism match #4489 very closely. That issue covered 0.14.0/0.14.1 fresh installs and was closed by stale automation without a linked fix. This report confirms the same failure on 0.14.2 and during an update to an existing AutoscalingRunnerSet.
Recovery/workaround:
AutoscalingListener.spec.ephemeralRunnerSetNameis not the single active EphemeralRunnerSet.updateStrategy=eventual, ARC drains running jobs, creates the replacement EphemeralRunnerSet/listener, and recovers.We currently run that check as a post-sync hook because the controller did not self-heal the stale reference.
Describe the expected behavior
After replacing an EphemeralRunnerSet, ARC should atomically create/update the listener against the surviving set, or reconcile and replace any listener whose
spec.ephemeralRunnerSetNamepoints to a missing/non-current set.A listener pod restart should not repeatedly inherit a permanently stale generated resource name.
Additional Context
Controller Logs
Complete captured controller log window (the controller includes the terminated listener's full output in
message):https://gist.github.com/DocX/80b533f37c0bd1a5253fdd8514df6609
The first entry already contains the decisive listener error; the recreate loop continues throughout the capture.
Runner Pod Logs
No runner pod failure was involved. The failing pod was the AutoscalingListener, and its complete output is embedded in the controller termination messages in the gist above. Runner creation/assignment was blocked because the listener could not patch its referenced EphemeralRunnerSet.