Skip to content
Latchkey LogoLatchkey home

Job killed no output watchdog errors in CI

A job killed no output watchdog message means some CI system decided a silent step was a hung step and terminated it, and the first useful thing to know is which system, because they do not all have one. Travis CI and CircleCI both kill on an idle log timer; GitHub Actions has no idle timer at all, so a quiet job that died there died of something else and the log will say so.

Three CI systems and what ends a silent job: an idle log timer, a step setting, or no idle timer at all
What each system does with a step that produces no output. GitHub Actions limits from docs.github.com/en/actions/reference/limits, read on 21 September 2026.

What this error means

The build stops in the middle of a long, quiet step and the log ends with a sentence about output not having been received, followed by a link and a statement that the build was terminated. There is no stack trace, no non-zero exit from your own command, and re-running frequently succeeds, which is what makes this read as flakiness rather than as a rule being enforced. The duration in the message is a value interpolated from the worker's configured log timeout rather than a fixed part of the sentence, so the number changes between installations. A shortened version of this message ending in the words "Terminating the job" circulates widely and is not what the emitting code prints, so if that is the form you are matching against, you are matching a paraphrase.

Reconstructed from travis-ci/worker step_run_script.go
No output has been received in the last 10m0s, this potentially indicates a stalled build or something wrong with the build itself.
Check the details on how to adjust your build configuration on: https://docs.travis-ci.com/user/common-build-problems/#build-times-out-because-no-output-was-received

The build has been terminated

Identify the system before you change anything

The sentence quoted above is Travis CI's. It is emitted by the Travis worker when the channel it uses to watch the log fires its timeout, in a branch that writes the message, marks the job errored and stops the machine. The duration in the text is filled in from the worker's own log timeout setting, so the number you see is configuration rather than a constant.

CircleCI has the same concept under a different name and a different message: an idle timeout you configure per step, spelled no_output_timeout in the configuration reference, which is why the fix there is a key in your config file rather than a change to what your command prints.

GitHub Actions does not have this mechanism. Nothing in its published limits is an idle-output timer, which means no GitHub Actions job has ever been killed for being quiet. If a quiet job died on GitHub Actions, it hit one of a short list of other ceilings, and each of those prints something different from the message above.

Common causes

A long step that genuinely produces no output

A large compile, a quiet test runner, a database restore or a slow upload can work steadily for many minutes without writing a line. On a platform with an idle timer that is indistinguishable from a hang, so the job is killed while making progress. This is the cause the message was written for and it is the one that is actually happening most of the time.

Output that exists but never reaches the log

This is the trap, because the step is not quiet: the process is writing, and the writes are sitting in a buffer. Most runtimes switch from line buffering to block buffering when standard output is a pipe rather than a terminal, which is exactly what CI gives them, so a tool that prints a progress line every second locally prints nothing at all for minutes under CI and then everything at once. The watchdog sees the same silence either way.

The step is genuinely hung

Sometimes the watchdog is right. A process waiting on a lock that will never be released, a prompt nobody will answer, or a network read with no timeout will sit there until something kills it. The tell is that raising the idle timeout changes only how long you wait for the same outcome, which is worth knowing before you raise it twice.

You are on GitHub Actions and this is a different failure

If the platform is GitHub Actions, no idle timer exists, so the silence is a symptom rather than the cause. The job was cancelled by timeout-minutes, by the 6-hour execution ceiling, by the queue or run limits, or the runner stopped communicating. Each of those says something specific in the log, and none of them says anything about output not being received.

How to fix it

Unbuffer the output before you touch any timeout

This is first because it costs nothing and it fixes the case where the job was working. Force line buffering on the process and the progress you already produce reaches the log, which satisfies the watchdog and gives you a usable record of where a slow step spends its time. It is also the only fix here that improves the log for every future run rather than only for this failure.

Terminal
stdbuf -oL -eL ./long-build.sh

# per-runtime equivalents
PYTHONUNBUFFERED=1 python -u ./slow_task.py
RUST_LOG=info cargo build --verbose
mvn -B install   # batch mode prints progress without the transfer spinner

Emit a heartbeat around a step that truly cannot speak

Where the quiet command has no verbose mode worth using, print alongside it. A background loop writing a timestamp every minute keeps the log active for the length of the step and stops the moment the real work finishes. Keep the interval well under the idle timeout, and capture the loop's process id so the step does not outlive its own heartbeat.

Terminal
( while true; do echo "still building at $(date +%T)"; sleep 60; done ) &
KEEPALIVE=$!
trap 'kill "$KEEPALIVE" 2>/dev/null' EXIT
./long-build.sh

Raise the idle timeout on the platform that has one

  1. On CircleCI, set no_output_timeout on the step that is being killed rather than globally, so a genuinely hung step elsewhere is still caught.
  2. On Travis CI, the log timeout is a worker setting rather than something a build can extend arbitrarily, so treat output as the primary fix and the timeout as the exception.
  3. On GitHub Actions there is nothing to raise, because there is no idle timer. Set timeout-minutes on the job to a value above the step's real duration instead, and remember it is measuring total time.
.github/workflows/ci.yml
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 90
    steps:
      - run: ./long-quiet-build.sh
        timeout-minutes: 75

Decide whether it was hung, using the log you now have

Once output is flowing, the same failure tells you something. If the heartbeat keeps printing while the tool prints nothing new for the whole window, the tool is stuck and the timeout was correct. If the tool resumes printing after a long gap, it was working and buffering, and you have already fixed it. Do this before raising any limit, because a raised limit on a genuinely hung step buys nothing but a larger bill.

What actually ends a quiet job on GitHub Actions

There are five, and they are all clocks on total elapsed time rather than on silence. A job is cancelled when it passes timeout-minutes, which defaults to 360. A hosted job is terminated at 6 hours of execution time whatever the timeout says, and a self-hosted job at 5 days. A job sitting in the queue is cancelled after 24 hours. A whole workflow run is cancelled at 35 days, counting waiting and approval time as well as execution.

The sixth possibility is not a clock. If the runner stops talking to the service, the job ends with a message about communication rather than about output, and that is a different page: the runner lost communication with the server covers what that means and what causes it.

So the diagnostic on GitHub Actions is to read the last line rather than the length of the silence. A cancellation at exactly 360 minutes is the default job timeout doing its job. A cancellation at 6 hours is the platform limit. A step that ran for eleven minutes and stopped is none of these, and you are looking at a different failure that happens to have been quiet.

SystemIs there an idle-output timer?What you change
Travis CIYes, in the workerEmit output, or raise the worker log timeout
CircleCIYes, per stepThe no_output_timeout key on the step
GitHub ActionsNotimeout-minutes, which is a total-time limit, not an idle one

Why there is no recorded run on this page

Our runners are GitHub Actions runners, and the mechanism this page is about does not exist there, so there is nothing for us to reproduce. We could run a step that stays quiet for an hour and it would simply stay quiet for an hour, which demonstrates the absence rather than the failure and would be a strange thing to publish as evidence.

Reproducing the message itself would mean running a Travis CI build, and a log from a competitor's platform is not runner evidence in any sense we are willing to claim. The honest position is that the quote above comes from the source that prints it, which anyone can open and check line by line, and that the GitHub Actions half of the page rests on published limits rather than on anything we observed.

How to prevent it

  • Run build tools unbuffered or in a batch or verbose mode that prints progress.
  • Give any step that can legitimately run quiet for minutes a heartbeat rather than a larger timeout.
  • Set timeout-minutes on every GitHub Actions job, since the default ceiling is 360 minutes of billed time.
  • Keep the per-step timeout below the job timeout so the log names the step that hung.
  • When you port a pipeline between CI systems, port the idle-timeout assumptions too: not every platform has one.

Frequently asked questions

Does GitHub Actions kill a job for producing no output?
No. Nothing in the published Actions limits is an idle-output timer. A GitHub Actions job ends because it passed timeout-minutes, hit the 6-hour hosted execution limit or the 5-day self-hosted one, waited 24 hours in the queue, reached the 35-day run limit, or because the runner stopped communicating with the service.
Which CI system prints "No output has been received in the last 10m0s"?
Travis CI. The line is produced by the Travis worker when its log-watching channel times out, and the duration is interpolated from that worker's configured log timeout rather than being fixed at ten minutes. CircleCI has the same idea under the no_output_timeout step key, with different wording.
My step works locally and goes silent in CI. Why?
Almost always output buffering. Many runtimes switch from line buffering to block buffering when standard output is a pipe instead of a terminal, which is what CI provides, so progress that appears immediately on your machine is held in a buffer for minutes under CI. Run the tool through stdbuf -oL, or set its own unbuffered flag.
Should I just raise the timeout?
Only after you know the step was working. Raising an idle timeout on a genuinely hung step changes how long you wait and how much you are billed, and nothing else. Make the step print first: if the output resumes after a long gap it was buffering, and if it never resumes the timeout was doing its job.

Related guides

References

GitHub Actions has no idle timer at all. Latchkey runs Actions jobs at $0.0025/min at 2 vCPU. Start free → 30-day trial · No credit card