GitHub Actions step debug logs truncated, and where the rest is
GitHub Actions step debug logs truncated describes a problem with reading the log rather than with the log itself, and that distinction is the whole fix: the stored run log is not the thing that gave up. Before hunting for a size limit, get the archive, because the line you want is very often already in it.

What this error means
You switch on step debug logging to chase something, re-run the job, and the web view of the step will not show you what you came for. The view is slow to open, scrolling stalls, and the part of the output you need is above or below whatever the browser is willing to render. What makes this frustrating is that the run succeeded in producing the output: the command wrote it, the runner uploaded it, and only the last step of getting it in front of you has failed.
gh run download <run-id> --log > run.log # the archive, not the viewer
wc -l run.logA note on the message people expect to find
Many descriptions of this problem quote a warning line saying that the logs for a step have been truncated because they exceeded a maximum size. We went looking for that line and could not establish it. Searched as an exact phrase and as its longest fragment, with a nonsense phrase of the same shape as a control returning nothing and real messages returning results that did contain them, the phrase produced no report whose body carried it once fetched and searched.
It is also absent from the sources you can read. The runner repository does not contain it, and the documentation on run logs and on debug logging does not describe a truncation warning or publish a step log size limit. The documented limits page covers workflow file size, job concurrency and storage, and says nothing about the size of a step log.
The honest conclusion is narrow. A sentence that is widely repeated is not one we can attribute to anything, and we are not going to repeat it as though it were quoted. What people do reliably experience is a web view that will not show them everything, which is a real problem with a real answer, and the rest of this page is about that.
| How you read the output | What you get | Limited by rendering |
|---|---|---|
| The step view in the browser | as much as the page will render | yes |
| The downloaded run log archive | the stored log for every job | no |
| An artifact you uploaded yourself | exactly what you redirected into it | no |
| The runner diagnostic logs | the runner and worker process logs | no |
Common causes
Step debug logging was left on repository wide
The switch is not scoped to one workflow or one job, so every run in the repository becomes verbose until somebody removes it. A single investigation can make every log in the repository harder to read for as long as it stays set.
A tool was run at its most verbose setting
Build tools, package managers and test runners can produce enormous output on request. A verbosity flag added during one investigation and never removed is the usual origin of a permanently unreadable step.
The output belongs in a file rather than in the log
Large structured output, reports and traces are better as artifacts. Putting them in the log makes them hard to read and hard to keep, since a log is not a convenient thing to hand to somebody else.
The browser is the constraint, not the log
In our experience this is where most of the confusion sits. The stored log is complete, and the view of it is the part that is failing, which is why downloading the archive so often ends the problem in one command.
How to fix it
Download the log archive and search it
- Download the run log rather than scrolling the step view.
- Search the downloaded file for the text you need.
- If you need a different job from the same run, it is in the same archive.
gh run download <run-id> --log > run.log
grep -n -C3 'error' run.logRedirect verbose output into an artifact
Capture the noisy command into a file, upload the file, and print it only when the step fails. The log stays readable and the full output is downloadable for as long as the artifact is retained.
- run: npm run build --verbose > build.log 2>&1 || { tail -50 build.log; exit 1; }
- if: always()
uses: actions/upload-artifact@v4
with:
name: build-log
path: build.logTurn step debug logging off again
Remove the repository secret or variable once the investigation is finished. Treat it as a temporary change with an owner, not as a setting that can be left on because it is sometimes useful.
Use the debug context to be verbose only when watched
Guard expensive or noisy steps on the runner debug context so they run when somebody has actually turned debug logging on. This keeps the ordinary log clean without losing the detail when it is wanted.
- if: runner.debug == '1'
run: |
env | sort
cat package-lock.json | head -100Add the runner diagnostic logs when the question is about the runner
Setting the runner debug variable adds the runner and worker process logs to the archive. Use it when a step did not start or the job set up looks wrong, rather than when a command printed too much.
Getting the whole log, and what the archive contains
The stored log for a run can be downloaded as an archive, and that is the copy to work with whenever the browser is struggling. It contains the log for every job in the run, so it also answers questions the step view makes awkward, such as what a different job was doing at the same moment.
Once it is on disk the tools are the ordinary ones. Searching a file for a pattern is faster and more reliable than scrolling, and it does not care how large the file is. This is usually the entire fix, and it takes less time than reading an explanation of a size limit.
There is a second switch worth knowing about, distinct from step debug logging. Turning on runner diagnostic logging adds two files to the archive, one from the runner process about coordinating and setting up the job and one from the worker process about executing it. Those answer questions about the runner rather than about your commands, which makes them the right tool when the problem is that a step did not start rather than that it printed too much.
gh run download <run-id> --log > run.log
grep -n 'the thing you are looking for' run.log
# or from the API
gh api repos/OWNER/REPO/actions/runs/<run-id>/logs > logs.zipProducing less, so there is less to read
Step debug logging is a repository wide switch. Setting it affects every job in every workflow in that repository until it is turned off, which is why a single investigation can make everybody logs unreadable for a week. Turn it off when you are done, and treat leaving it on as a change rather than a convenience.
Where the noise comes from your own commands rather than from the runner, redirect it. Sending verbose output to a file and uploading that file as an artifact gives you a complete copy that was never in the log at all, and it keeps the step view usable for the rest of the job. Print the file on failure so a red run still carries its evidence.
There is also a context that lets a workflow know whether debug logging is on, which means a step can decide to be verbose only when somebody is actually looking. That is a better pattern than a permanently noisy step, because it gives you the output when you want it and costs nothing when you do not.
- name: Build
run: npm run build --verbose > build.log 2>&1 || { cat build.log; exit 1; }
- if: always()
uses: actions/upload-artifact@v4
with:
name: build-log
path: build.log
- if: runner.debug == '1'
run: env | sortWhy there is no recorded run on this page
The subject here is a browser failing to render a large page, which is not a property of a run at all. A recording would be a video of our browser on our machine, and the thing it demonstrated would be our hardware and our connection rather than anything about GitHub Actions.
It would also be the wrong evidence for the most important claim on the page, which is a negative one. The way to support the statement that the expected warning line cannot be attributed is to describe the search and its controls, which is done above, not to produce a run that does not show it.
Nor is there anything to repair. A log that is too large to render comfortably is a successful log, and the command that wrote it did what it was told.
How to prevent it
- Treat step debug logging as a temporary change with somebody responsible for removing it.
- Send large or structured output to an artifact rather than to the log.
- Guard noisy diagnostic steps on the runner debug context.
- Reach for the downloaded archive before you fight the web viewer.