Skip to content

Fix TypeError in truncate_serialized_error when message is None#33667

Open
Krishnachaitanyakc wants to merge 1 commit intodagster-io:masterfrom
Krishnachaitanyakc:fix/truncate-serialized-error-none-message
Open

Fix TypeError in truncate_serialized_error when message is None#33667
Krishnachaitanyakc wants to merge 1 commit intodagster-io:masterfrom
Krishnachaitanyakc:fix/truncate-serialized-error-none-message

Conversation

@Krishnachaitanyakc
Copy link
Copy Markdown

Summary

Fixes #33662

  • Bug: truncate_serialized_error calls len(error_info.message) without guarding against None. When deserializing older event log entries, the message field of SerializableErrorInfo can be None (the @record decorator has checked=False, so runtime type enforcement is disabled). This causes a TypeError: object of type 'NoneType' has no len() crash when viewing failed runs in the Dagster UI via the RunStepStatsQuery GraphQL query.

  • Fix: Fall back to an empty string (error_info.message or "") before computing the length and slicing, consistent with the defensive pattern already used for cls_name on the same function (line 271: if error_info.cls_name and len(...)).

  • Test: Added a regression test test_truncate_serialized_error_none_message that constructs a SerializableErrorInfo with message=None and verifies truncate_serialized_error handles it without raising.

Test plan

  • Added test_truncate_serialized_error_none_message regression test
  • Existing test_truncate_serialized_error continues to pass
  • Manual verification: the fix matches exactly what the issue reporter validated in their own environment

When deserializing older event log entries, the `message` field of
`SerializableErrorInfo` can be `None`. The `truncate_serialized_error`
function called `len(error_info.message)` without guarding against
`None`, causing a `TypeError: object of type 'NoneType' has no len()`
when viewing failed runs in the UI (via the `RunStepStatsQuery` GraphQL
query).

Fix by falling back to an empty string before computing the length,
matching the defensive pattern already used for `cls_name` on line 271.

Adds a regression test for the None message case.

Fixes dagster-io#33662
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 25, 2026

Greptile Summary

This PR fixes a TypeError crash in truncate_serialized_error when error_info.message is None, which can happen when deserializing older event log entries stored with the @record(checked=False) decorator. The fix adds a defensive or "" fallback before computing len() and slicing, consistent with the existing guard already applied to cls_name in the same function.

Key changes:

  • error.py: Replaces len(error_info.message) with msg = error_info.message or "" / len(msg), and uses msg for slicing, ensuring None messages are handled gracefully and the original None is preserved when no truncation is needed.
  • test_errors.py: Adds a targeted regression test test_truncate_serialized_error_none_message that constructs a SerializableErrorInfo with message=None, invokes truncate_serialized_error, and asserts no exception is raised and the None value is preserved.

Confidence Score: 5/5

  • This PR is safe to merge — it is a minimal, targeted bug fix with a regression test and no side effects on the normal code path.
  • The change is a one-line defensive guard that exactly mirrors the existing cls_name guard in the same function, produces no behavioral change for non-None messages, and is covered by a new regression test. The risk surface is essentially zero.
  • No files require special attention.

Important Files Changed

Filename Overview
python_modules/dagster/dagster/_utils/error.py Adds a None guard for error_info.message before calling len(), fixing a TypeError crash when deserializing older event log entries with a None message field.
python_modules/dagster/dagster_tests/utils_tests/test_errors.py Adds test_truncate_serialized_error_none_message regression test that verifies truncate_serialized_error no longer raises TypeError when message=None, and confirms the None value is preserved in the result.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[truncate_serialized_error called] --> B{error_info.message is None?}
    B -- Yes --> C["msg = '' (empty string)"]
    B -- No --> D["msg = error_info.message"]
    C --> E["msg_len = len(msg)  →  0"]
    D --> F["msg_len = len(msg)"]
    E --> G{"msg_len > field_size_limit?"}
    F --> G
    G -- No --> H[message unchanged / None preserved]
    G -- Yes --> I["error_info._replace(message=msg[:limit] + ' (TRUNCATED)')"]
Loading

Reviews (1): Last reviewed commit: "Fix TypeError in truncate_serialized_err..." | Re-trigger Greptile

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.

Message: object of type 'NoneType' has no len()

1 participant