Skip to content

Truncate RPC error text on a UTF-8 boundary - #1018

Closed
RaphaelFakhri wants to merge 2 commits into
livekit:mainfrom
RaphaelFakhri:fix/truncate-bytes-utf8
Closed

RaphaelFakhri wants to merge 2 commits into
livekit:mainfrom
RaphaelFakhri:fix/truncate-bytes-utf8

Conversation

@RaphaelFakhri

Copy link
Copy Markdown

Fixes #1017

Summary

truncateBytes cuts strings at a byte offset. When the offset falls inside a multi-byte UTF-8 character, NewRpcError produces an invalid string, and proto.Marshal fails with string field contains invalid UTF-8 when the error is sent.

This change backs the cut point up to the start of the character, so the result is valid UTF-8 and never exceeds the byte limit.

Testing

  • Adds TestTruncateBytes covering ASCII, exact-fit, and cuts inside 2-, 3-, and 4-byte characters.
  • Adds TestNewRpcErrorTruncatesToValidUTF8, which marshals the truncated error.
  • Both tests fail on main and pass with this change.

@RaphaelFakhri
RaphaelFakhri requested a review from a team as a code owner September 29, 2026 10:02
@CLAassistant

CLAassistant commented Sep 29, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 2 potential issues.

Devin Review

Comment thread utils.go Outdated
for end > 0 && !utf8.RuneStart(str[end]) {
end--
}
return str[:end]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Truncated errors retain discarded payloads

When NewRpcError receives an oversized string, truncateBytes keeps its entire backing allocation through the returned substring. Retained errors therefore keep discarded message or data bytes in memory.

Suggested change
return str[:end]
return strings.Clone(str[:end])

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread utils.go
@RaphaelFakhri

Copy link
Copy Markdown
Author

Truncated errors retain discarded payloads

Valid finding, fixed in the new commit. truncateBytes now returns strings.Clone(str[:end]), so a truncated error no longer keeps the discarded tail of the original string alive.

Malformed error text still blocks responses

Valid finding, fixed in the same commit. truncateBytes now drops malformed UTF-8 with strings.ToValidUTF8 before it checks the length, so the result is valid for protobuf string fields for both short and long inputs, in the message and in the data. The tests cover invalid bytes within the limit, before the cut, after the cut, and as a truncated sequence at the end, plus a marshal check on NewRpcError.

notify-devs check

The failure is unrelated to the change. The job fails in the livekit/slack-notifier-action step, which needs repository secrets that are not available to a pull request from a fork.

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.

NewRpcError truncation can split a multi-byte UTF-8 character

2 participants