act_runner registers successfully (Declare 200 OK) but never sends FetchTask — jobs stuck "no matching online runner"

Environment:

  • Gitea server version: 1.25.3
  • act_runner: tested both v0.2.13 and latest (v0.6.1) — identical behavior on both
  • Host: ARM64 (NVIDIA DGX Spark)
  • Deployment: docker-compose, all self-hosted. Services: gitea, gitea-db (postgres:16), gitea-cache (redis:6-alpine), gitea-runner
  • gitea and gitea-runner share a custom Docker network local, defined as internal: true (no outbound internet route by design)
  • Runner’s GITEA_INSTANCE_URL set to internal service address http://gitea:3000
  • Registered with an instance-wide admin token
  • /var/run/docker.sock bind-mounted; runner runs as root; socket perms srw-rw---- root:988 — fully accessible

Symptom:

  • Runner log on every startup shows registration succeeding cleanly, then nothing else ever — not even at log.level: debug. No errors, no retries, no crash. Process stays alive (ps aux confirms), RestartCount: 0.
  • Server-side log shows the Declare call every time (200 OK), but never once a FetchTask call — across many restarts and both versions.
  • Admin UI shows the runner as “Idle” but last-contact is never populated.
  • Push or manual workflow_dispatch both create a run, but it never starts: “no matching runner with label ubuntu-latest online” (labels do match).

Already ruled out: clock skew (identical across host/containers), basic reachability (/api/healthz returns 200 OK anytime), Docker socket access, explicit docker_host config vs auto-detect, disabling the Actions cache server (cache.enabled: false), config-file .runner persistence (confirmed working), crash-looping (none).

Question: What would cause the runner to Declare successfully but never attempt FetchTask, with zero logged errors even at debug? Known interaction with instance-wide tokens, or with a fully outbound-isolated Docker network?

i have seen declare succeed while the runner never joins the poll loop when registration used an admin/api token instead of the runner registration token from site admin → actions → runners. worth re-registering with a fresh runner token and a clean .runner file.

also double-check config.yaml labels include ubuntu-latest exactly (same spelling the workflow asks for), and that the daemon keeps running after declare (not just the one-shot register command).

your internal: true network should still be fine for http://gitea:3000 polling. if healthz works but last-contact stays empty after a proper runner-token register, paste the runner config (redact tokens) and the first 30s of debug log after daemon start.

thanks a lot

problem is solved