Skip to content

Stream instance log lines longer than 64 KiB - #528

Open
RaphaelFakhri wants to merge 1 commit into
kernel:mainfrom
RaphaelFakhri:fix/instance-logs-long-lines
Open

RaphaelFakhri wants to merge 1 commit into
kernel:mainfrom
RaphaelFakhri:fix/instance-logs-long-lines

Conversation

@RaphaelFakhri

@RaphaelFakhri RaphaelFakhri commented Oct 25, 2026 •

Copy link
Copy Markdown

Summary

GET /instances/{id}/logs reads tail output with a bufio.Scanner that uses the default 64 KiB token limit. When a log contains a longer line, for example a large JSON record written by the guest app, Scan fails with bufio.ErrTooLong:

  • The long line and everything after it never reach the client.
  • The goroutine stops reading tail's stdout and then calls cmd.Wait(). tail blocks writing to the full pipe, so the SSE stream stays open with no output until the client disconnects, even with follow=false.

This change gives the scanner a split function that behaves like bufio.ScanLines, but returns a line longer than 64 KiB in pieces of at most 64 KiB instead of failing. A piece never ends inside a UTF-8 sequence, so the JSON-encoded SSE events do not contain replacement characters at the boundaries.

Testing

TestStreamInstanceLogsLongLine writes an app log with a short line, a line of about 400 KiB, and another short line, then streams it with follow=false. It checks that the stream closes, that the short lines arrive, that the pieces join back into the long line, and that every piece is valid UTF-8.

  • Without the fix: the test fails after its 10 second timeout with log stream did not finish; received 1 lines.
  • With the fix: the test passes.
go test -tags containers_image_openpgp ./lib/instances/ -run 'TestStreamInstanceLogsLongLine|TestShouldSkipAppLogLine|TestMacOSAppLogSourceIsNotSupported|TestVMMLogSourceFollowsMacOSShimLog' -count=1

Fixes #527


Note

Low Risk
Localized change to log line tokenization in the instances log stream; behavior improves edge cases without touching auth or persistence.

Overview
Fixes instance log streaming when a single line exceeds bufio.Scanner’s default 64 KiB limit (e.g. large JSON on one line). Previously bufio.ErrTooLong stopped the scanner, dropped the rest of the log, and could leave tail blocked on a full pipe so GET /instances/{id}/logs SSE hung until disconnect.

streamInstanceLogs now uses a custom scanLogLines split: normal newline behavior, but oversized lines are emitted as multiple chunks capped at maxLogLineBytes, with chunk boundaries adjusted so UTF-8 runes are not cut in half.

Adds TestStreamInstanceLogsLongLine to assert the stream completes, short lines are correct, chunks rejoin to the original long line, and every chunk is valid UTF-8.

Reviewed by Cursor Bugbot for commit 92b33cf. Bugbot is set up for automated code reviews on this repo. Configure here.

bufio.Scanner fails with ErrTooLong on a line over 64 KiB. The log stream then stops reading tail's output, so the rest of the log is lost and the stream stays open until the client disconnects. Return long lines in pieces instead, without splitting a UTF-8 sequence.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 92b33cf. Configure here.

Comment thread lib/instances/logs.go
break
}
}
return n, data[:n], nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-size lines emit extra blank

Low Severity

When a line is exactly maxLogLineBytes long (or an exact multiple) and then a newline, scanLogLines emits the content as a full-size piece before the newline is visible. ScanLines then treats that newline as its own empty token, so the SSE stream gets a spurious blank entry that was not in the log.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 92b33cf. Configure here.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Instance log stream stalls on a log line longer than 64 KiB

1 participant