Skip to content
Latchkey

GitHub Actions Per-Step timeout-minutes Not Cancelling a Hung Step

A hung step runs far longer than expected because timeout-minutes was placed at the wrong level. A job-level timeout-minutes caps the whole job; a step-level one must be set on the individual step to cancel just that step.

What this error means

A single command hangs for the full job timeout (or the 6-hour ceiling) instead of being cancelled quickly, because no step-level timeout-minutes applied to it.

.github/workflows/ci.yml
jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 30      # whole-job cap
    steps:
      - run: ./flaky.sh      # no per-step cap - can run the full 30m

Common causes

timeout-minutes at the job, not the step

A job-level timeout-minutes only cancels the entire job after the limit. To bound a single step, set timeout-minutes on that step.

No timeout at all on a hang-prone step

Without any timeout, a step blocked on a lock, prompt, or dead network waits until the job ceiling, wasting minutes.

How to fix it

Set timeout-minutes on the step

Add a tight per-step timeout so a hang fails that step in minutes.

.github/workflows/ci.yml
steps:
  - name: Integration tests
    run: ./integration.sh
    timeout-minutes: 10     # cancels just this step

Layer step and job timeouts

  1. Use step timeouts for individual hang-prone commands.
  2. Keep a job timeout as a safety ceiling for the whole job.
  3. Add non-interactive flags so steps do not block on input.

How to prevent it

  • Put timeout-minutes on hang-prone steps, not only on the job.
  • Keep a job-level timeout as an overall ceiling.
  • Run commands non-interactively so they never wait on a prompt.

Frequently asked questions

What causes "Per-step timeout"?
A job-level timeout-minutes only cancels the entire job after the limit. To bound a single step, set timeout-minutes on that step.
How do I fix Per-step timeout?
Add a tight per-step timeout so a hang fails that step in minutes.
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.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card