mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
feat(platform): Explain None Message in BlockError Messages (#11490)
Sometime block errors are raised with message set as None, we now handle
this case
### Changes 🏗️
- handle case of None message
- Add tests
### Checklist 📋
#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
<!-- Put your test plan here: -->
- [x] write unit tests
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Ensure `BlockExecutionError` and `BlockUnknownError` provide default
messages when given None/empty input, with new unit tests covering
formatting and inheritance.
>
> - **Backend**:
> - `backend/util/exceptions.py`:
> - `BlockExecutionError`: default `None` message to `"Output error was
None"`.
> - `BlockUnknownError`: default empty/`None` message to `"Unknown error
occurred"`.
> - **Tests**:
> - `backend/util/exceptions_test.py`: add tests for message formatting,
`None`/empty handling, and exception inheritance.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6e9b31ae47. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Nicholas Tindle <nicholas.tindle@agpt.co>
This commit is contained in:
@@ -21,10 +21,20 @@ class BlockOutputError(BlockError, ValueError):
|
||||
class BlockExecutionError(BlockError, ValueError):
|
||||
"""The block failed to execute at runtime, resulting in a handled error"""
|
||||
|
||||
def __init__(self, message: str | None, block_name: str, block_id: str) -> None:
|
||||
if message is None:
|
||||
message = "Output error was None"
|
||||
super().__init__(message, block_name, block_id)
|
||||
|
||||
|
||||
class BlockUnknownError(BlockError):
|
||||
"""Critical unknown error with block handling"""
|
||||
|
||||
def __init__(self, message: str | None, block_name: str, block_id: str) -> None:
|
||||
if not message:
|
||||
message = "Unknown error occurred"
|
||||
super().__init__(message, block_name, block_id)
|
||||
|
||||
|
||||
class MissingConfigError(Exception):
|
||||
"""The attempted operation requires configuration which is not available"""
|
||||
|
||||
125
autogpt_platform/backend/backend/util/exceptions_test.py
Normal file
125
autogpt_platform/backend/backend/util/exceptions_test.py
Normal file
@@ -0,0 +1,125 @@
|
||||
from backend.util.exceptions import (
|
||||
BlockError,
|
||||
BlockExecutionError,
|
||||
BlockInputError,
|
||||
BlockOutputError,
|
||||
BlockUnknownError,
|
||||
)
|
||||
|
||||
|
||||
class TestBlockError:
|
||||
"""Tests for BlockError and its subclasses."""
|
||||
|
||||
def test_block_error_message_format(self):
|
||||
"""Test that BlockError formats the message correctly."""
|
||||
error = BlockError(
|
||||
message="Test error", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert (
|
||||
str(error)
|
||||
== "raised by TestBlock with message: Test error. block_id: test-123"
|
||||
)
|
||||
|
||||
def test_block_input_error_inherits_format(self):
|
||||
"""Test that BlockInputError uses parent's message format."""
|
||||
error = BlockInputError(
|
||||
message="Invalid input", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert "raised by TestBlock with message: Invalid input" in str(error)
|
||||
|
||||
def test_block_output_error_inherits_format(self):
|
||||
"""Test that BlockOutputError uses parent's message format."""
|
||||
error = BlockOutputError(
|
||||
message="Invalid output", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert "raised by TestBlock with message: Invalid output" in str(error)
|
||||
|
||||
|
||||
class TestBlockExecutionErrorNoneHandling:
|
||||
"""Tests for BlockExecutionError handling of None messages."""
|
||||
|
||||
def test_execution_error_with_none_message(self):
|
||||
"""Test that None message is replaced with descriptive text."""
|
||||
error = BlockExecutionError(
|
||||
message=None, block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert "Output error was None" in str(error)
|
||||
assert "raised by TestBlock with message: Output error was None" in str(error)
|
||||
|
||||
def test_execution_error_with_valid_message(self):
|
||||
"""Test that valid messages are preserved."""
|
||||
error = BlockExecutionError(
|
||||
message="Actual error", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert "Actual error" in str(error)
|
||||
assert "Output error was None" not in str(error)
|
||||
|
||||
def test_execution_error_with_empty_string(self):
|
||||
"""Test that empty string message is NOT replaced (only None is)."""
|
||||
error = BlockExecutionError(
|
||||
message="", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
# Empty string is falsy but not None, so it's preserved
|
||||
assert "raised by TestBlock with message: . block_id:" in str(error)
|
||||
|
||||
|
||||
class TestBlockUnknownErrorNoneHandling:
|
||||
"""Tests for BlockUnknownError handling of None/empty messages."""
|
||||
|
||||
def test_unknown_error_with_none_message(self):
|
||||
"""Test that None message is replaced with descriptive text."""
|
||||
error = BlockUnknownError(
|
||||
message=None, block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert "Unknown error occurred" in str(error)
|
||||
|
||||
def test_unknown_error_with_empty_string(self):
|
||||
"""Test that empty string is replaced with descriptive text."""
|
||||
error = BlockUnknownError(
|
||||
message="", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert "Unknown error occurred" in str(error)
|
||||
|
||||
def test_unknown_error_with_valid_message(self):
|
||||
"""Test that valid messages are preserved."""
|
||||
error = BlockUnknownError(
|
||||
message="Something went wrong", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert "Something went wrong" in str(error)
|
||||
assert "Unknown error occurred" not in str(error)
|
||||
|
||||
|
||||
class TestBlockErrorInheritance:
|
||||
"""Tests for proper exception inheritance."""
|
||||
|
||||
def test_block_execution_error_is_value_error(self):
|
||||
"""Test that BlockExecutionError is a ValueError."""
|
||||
error = BlockExecutionError(
|
||||
message="test", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert isinstance(error, ValueError)
|
||||
assert isinstance(error, BlockError)
|
||||
|
||||
def test_block_input_error_is_value_error(self):
|
||||
"""Test that BlockInputError is a ValueError."""
|
||||
error = BlockInputError(
|
||||
message="test", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert isinstance(error, ValueError)
|
||||
assert isinstance(error, BlockError)
|
||||
|
||||
def test_block_output_error_is_value_error(self):
|
||||
"""Test that BlockOutputError is a ValueError."""
|
||||
error = BlockOutputError(
|
||||
message="test", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert isinstance(error, ValueError)
|
||||
assert isinstance(error, BlockError)
|
||||
|
||||
def test_block_unknown_error_is_not_value_error(self):
|
||||
"""Test that BlockUnknownError is NOT a ValueError."""
|
||||
error = BlockUnknownError(
|
||||
message="test", block_name="TestBlock", block_id="test-123"
|
||||
)
|
||||
assert not isinstance(error, ValueError)
|
||||
assert isinstance(error, BlockError)
|
||||
Reference in New Issue
Block a user