Visitar URL original
`gh run view --log` silently drops the rest of a step after a log line longer than 64 KiB · Issue #15019 · cli/cli · GitHub
Skip to content

gh run view --log silently drops the rest of a step after a log line longer than 64 KiB #15019

Open

Agent suggestions

Public preview

Description

@jeffwall-curlewlabs

Describe the bug

gh run view --log (and --log-failed) silently drops everything after a log line longer than 64 KiB, up to the end of the log segment being printed. That is the rest of the step when gh can split the job's log into steps, or the rest of the job when it prints the job as one UNKNOWN STEP segment. There is no warning and the command exits 0, so the output looks complete when it isn't.

The cause is copyLogWithLinePrefix in pkg/cmd/run/view/view.go:

func copyLogWithLinePrefix(w io.Writer, r io.Reader, prefix string) error {
	sanitized := transform.NewReader(r, &asciisanitizer.Sanitizer{})
	scanner := bufio.NewScanner(sanitized)
	for scanner.Scan() {
		fmt.Fprintf(w, "%s%s\n", prefix, scanner.Text())
	}
	return nil
}

bufio.NewScanner has a default max token size of 64 KiB (bufio.MaxScanTokenSize). When a line exceeds it, Scan() returns false with bufio.ErrTooLong, and scanner.Err() is never checked, so the loop ends early for that segment and the function returns nil. displayLogSegments then moves on to the next segment, which is why the loss is per step.

Lines this long are common in real job logs: tools that print JSON event streams (for example, AI code-review CLIs emitting one JSON object per line) or build tools dumping a large status line.

Affected version

gh version 2.102.1 (2026-10-20)

The function is unchanged on trunk as of v2.103.3.

Steps to reproduce the behavior

I haven't run this minimal workflow; it is the smallest case the code above implies. The measurements further down come from real runs.

  1. Run a workflow with a step that prints a line longer than 64 KiB followed by a marker, e.g.:

    - run: |
        python3 -c "print('x' * 70000)"
        echo "AFTER-LONG-LINE"
  2. gh run view <run-id> --log | grep -c AFTER-LONG-LINE prints 0.

  3. gh api repos/<owner>/<repo>/actions/jobs/<job-id>/logs | grep -c AFTER-LONG-LINE prints 1.

Expected vs actual behavior

Expected: the whole log is printed, or, failing that, gh reports an error instead of exiting 0 with partial output.

Actual: the segment's output silently ends at the line before the over-long one, and the next step's output follows as if nothing were missing.

What I measured, on a private repository's runs: across six completed runs of one workflow, gh run view --attempt 1 --log was missing part of a job's log in five, while the run's log archive (/actions/runs/<id>/attempts/1/logs) had all of it. The one complete run was the only one with no line over 64 KiB. Across the six, the longest line gh printed was about 51,000 characters, and wherever I traced a cut, the dropped text began right at a line over 64 KiB. In a job from a different workflow, gh printed 2,932 of the job's 13,718 lines: one step was cut right before a line of about 139,000 characters, and thousands of lines of that step were never printed.

A possible fix: read with bufio.Reader.ReadString('\n') (no line-length limit), or give the scanner a buffer larger than any realistic log line (scanner.Buffer(...)). Checking scanner.Err() alone would surface the problem but still drop the rest of the segment.

Logs

N/A. The command exits 0 and logs nothing about the truncation.

Activity

  1. cli-triage commented on Nov 10, 2026

    @cli-triage

    Reproducible on 2.102.1.

    Using test data with a 198,689-byte job log containing a line over 64 KiB:

    $ gh run view 1 -R example.invalid/hello --log
    build	UNKNOWN STEP	/*!
    ...
    build	UNKNOWN STEP	    PERFORMANCE OF THIS SOFTWARE.

    Exit status: 0 (success). Output stopped at the oversized line and omitted the remaining log without an error. The same result occurred on release 2.103.3 and source revision 1837454. The current reader uses a default bufio.Scanner and does not return scanner.Err(), which matches the observed silent truncation.

    Supporting reports

    Generated by issue triage.

  2. xh123637 commented on Nov 13, 2026

    @xh123637

    The root cause here looks clear: copyLogWithLinePrefix uses a default bufio.Scanner and never checks scanner.Err(), so a line over 64 KiB silently ends the segment. A fix would raise the scanner buffer (or switch to a bufio.Reader loop) and surface scanner.Err() instead of returning nil, with a regression test feeding a >64 KiB line followed by a marker line.

    Would the team welcome a PR for this? Per CONTRIBUTING, external PRs need the help wanted label with explicit Acceptance Criteria — happy to wait for triage/labels before opening anything. @cli/code-reviewers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions