Skip to content

Conversation

@alexander-alderman-webb
Copy link
Contributor

@alexander-alderman-webb alexander-alderman-webb commented Nov 18, 2025

Description

Cast message and detail attributes on exceptions to string when generating the value attribute on the Sentry exception.

Resolves an unhandled TypeError when the message or detail attribute has type bytes and get_error_message() attempts to append string exception notes.

Issues

Fixes the exception described in #5050.

Reminders

@alexander-alderman-webb alexander-alderman-webb requested a review from a team as a code owner November 18, 2025 09:09
@alexander-alderman-webb alexander-alderman-webb marked this pull request as draft November 18, 2025 09:12
@alexander-alderman-webb alexander-alderman-webb marked this pull request as ready for review November 18, 2025 09:14
Comment on lines 657 to 660
message = str(
getattr(exc_value, "message", "")
or getattr(exc_value, "detail", "")
or safe_str(exc_value)
Copy link

Choose a reason for hiding this comment

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

Bug: Applying str() to a bytes object within get_error_message() results in literal b'...' prefixes in Sentry error messages.
Severity: CRITICAL | Confidence: 1.00

🔍 Detailed Analysis

If exc_value.message or exc_value.detail is a non-empty bytes object, the fix incorrectly wraps the entire or expression with str(). This converts the bytes object into its literal string representation (e.g., b"error" becomes "b'error'") instead of decoding it, resulting in malformed and unreadable error messages displayed in Sentry.

💡 Suggested Fix

Apply str() to each attribute individually before the or chain: str(getattr(exc_value, "message", "")) or str(getattr(exc_value, "detail", "")) or safe_str(exc_value).

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: sentry_sdk/utils.py#L657-L660

Potential issue: If `exc_value.message` or `exc_value.detail` is a non-empty bytes
object, the fix incorrectly wraps the entire `or` expression with `str()`. This converts
the bytes object into its literal string representation (e.g., `b"error"` becomes
`"b'error'"`) instead of decoding it, resulting in malformed and unreadable error
messages displayed in Sentry.

Did we get this right? 👍 / 👎 to inform future reviews.

Reference_id: 2759871

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess we could special case for bytes to avoid the prefix, but I'm not sure if the bytes prefix is a bug.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is fine. But I'd use safe_str instead of pure str.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice, changed!

Regarding Sentry's comment: previously, having bytes as the detail attribute always resulted in a TypeError as we try to append "\n" in all cases. Since the error was previously not captured, the case is not a breaking change.

message += "\n" + "\n".join(note for note in notes if isinstance(note, str))

@codecov
Copy link

codecov bot commented Nov 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.02%. Comparing base (66be3d2) to head (93f2cc7).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5114      +/-   ##
==========================================
+ Coverage   84.00%   84.02%   +0.01%     
==========================================
  Files         180      180              
  Lines       18030    18030              
  Branches     3209     3209              
==========================================
+ Hits        15147    15149       +2     
+ Misses       1906     1905       -1     
+ Partials      977      976       -1     
Files with missing lines Coverage Δ
sentry_sdk/utils.py 86.30% <100.00%> (ø)

... and 2 files with indirect coverage changes

Copy link
Contributor

@sentrivana sentrivana left a comment

Choose a reason for hiding this comment

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

LGTM, see comment.

Comment on lines 657 to 660
message = str(
getattr(exc_value, "message", "")
or getattr(exc_value, "detail", "")
or safe_str(exc_value)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is fine. But I'd use safe_str instead of pure str.

@alexander-alderman-webb alexander-alderman-webb merged commit c68c3d6 into master Nov 18, 2025
132 checks passed
@alexander-alderman-webb alexander-alderman-webb deleted the webb/cast-exception-message branch November 18, 2025 13:07
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.

3 participants