A step ran past its timeout-minutes and was cancelled. This guards against hangs, but a transient slowdown (slow fetch, not-yet-ready service) can also trip it on otherwise healthy work.
What this error means
A step ends with a cancellation noting the timeout was reached. If a transient slowdown caused it, a re-run completes; a true hang reproduces every time.
github-actions
##[error] The action 'Run tests' has timed out after 15 minutes.
Common causes
A transient slowdown exceeded the limit
A slow download or a service that took longer than usual to respond pushed the step past its timeout.
The step actually hangs
A deadlock, interactive prompt, or waiting on something that never arrives runs until the timeout fires.
How to fix it
Diagnose hang vs slow
Add verbose logging to see where the step stalls.
Ensure no command waits on interactive input (use non-interactive flags).
Add an internal timeout to the slow command so it fails fast with context.
Speed up or raise the limit
Cache to cut runtime, or bump the timeout if the work is legitimately longer.
shell
timeout 600 ./long-task.sh # fail fast with context
# or raise timeout-minutes in the step
How to prevent it
Set timeout-minutes to a realistic ceiling per step.
Make commands non-interactive in CI.
For a transient infra slowdown, managed runners detect the mechanical blip and automatically retry, so a one-off slow step does not fail the build.
Frequently asked questions
What causes "timeout-minutes exceeded"?
A slow download or a service that took longer than usual to respond pushed the step past its timeout.
How do I fix timeout-minutes exceeded?
Diagnose hang vs slow
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.