Improve metadata validation in message handlers and add test for inva…#335
Improve metadata validation in message handlers and add test for inva…#335Subhajitdas99 wants to merge 5 commits intoGetBindu:mainfrom
Conversation
|
##Summary Problem: message.metadata may be None or a non-dictionary value, which caused a TypeError when checking for _payment_context inside _submit_and_schedule_task. Why it matters: This could break message processing and cause runtime failures when metadata is missing or malformed. What changed: Added defensive normalization to ensure metadata is always a dictionary before accessing _payment_context, and added a unit test for invalid metadata types. What did NOT change (scope boundary): No changes to task scheduling logic, message processing flow, or streaming behavior. ##Change Type ##Scope ##Linked Issue/PR ##User-Visible / Behavior Changes ##Security Impact ##Verification ##Steps to Test ##Expected Behavior ##Actual Behavior ##Evidence -Example: ##Human Verification #Edge cases checked: #What you did NOT verify: ##Compatibility / Migration ##Failure Recovery
##Risks and Mitigations ##Checklist |
PR Review: #335 - Message Metadata Validation & Error HandlingSummaryThis PR improves robustness in the message handling code by adding validation for message metadata and better error logging. The changes prevent potential crashes when invalid metadata types are received and ensure consistent data structures throughout the message processing pipeline. Changes Overview1. Enhanced Metadata ValidationFile: Before: message_metadata = message.get("metadata", {})
if (
isinstance(message_metadata, dict)
and "_payment_context" in message_metadata
):
scheduler_params["payment_context"] = message_metadata["_payment_context"]
del message_metadata["_payment_context"]After: message_metadata = message.get("metadata")
# Normalize metadata to a dictionary
if message_metadata is None:
message_metadata = {}
message["metadata"] = message_metadata
elif not isinstance(message_metadata, dict):
logger.warning(
"Invalid metadata type received in message",
extra={"type": type(message_metadata).__name__}
)
message["metadata"] = {}
message_metadata = message["metadata"]
if "_payment_context" in message_metadata:
scheduler_params["payment_context"] = message_metadata["_payment_context"]
del message_metadata["_payment_context"]What this improves:
2. Empty Payload Guard in SSE Event SerializationBefore: @staticmethod
def _sse_event(payload: dict[str, Any]) -> str:
"""Serialize an SSE event payload."""
return f"data: {json.dumps(MessageHandlers._to_jsonable(payload))}\n\n"After: @staticmethod
def _sse_event(payload: dict[str, Any]) -> str:
"""Serialize an SSE event payload."""
if not payload:
return ""
return f"data: {json.dumps(MessageHandlers._to_jsonable(payload))}\n\n"What this improves:
3. Improved Error LoggingBefore: logger.error(
f"Unhandled stream error for task {task['id']}: {e}", exc_info=True
)After: logger.error(
"Unhandled stream error",
extra = {task['id': str(task["id"])]},
exc_info = True,
)What this improves:
Note: There appears to be a syntax error in the diff. The correct code should be: logger.error(
"Unhandled stream error",
extra={"task_id": str(task["id"])},
exc_info=True,
)The diff shows 4. Test CoverageFile: A new test was added: @pytest.mark.asyncio
async def test_send_message_invalid_metadata_type_handled():
"""
If metadata is not a dict, the handler should not crash and should normalize metadata safely.
"""
storage = InMemoryStorage()
handlers = _make_handlers(storage)
message = create_test_message(
text = "invalid metadata",
metadata = "this_should_be_a_dict"
)
request = _send_request(message)
response = await handlers.send_message(request)
assert_jsonrpc_success(response)
stored_task = await storage.load_task(response["result"]["id"])
stored_metadata = (stored_task["history"] or [{}])[-1].get("metadata", {})
#Metadata should be normalized to a dictionary
assert isinstance(stored_metadata, dict) What this validates:
Issues FoundCritical: Syntax Error in Logging CodeThe error logging change has a syntax error: extra = {task['id': str(task["id"])]}, # Wrong: mismatched brackets and quotesShould be: extra={"task_id": str(task["id"])},This will cause the code to fail at runtime when an exception occurs during streaming. Minor: Code Style Inconsistencies
RecommendationsMust Fix
Should Consider
VerdictREQUEST CHANGES - The PR has good intentions and improves code robustness, but the syntax error in the logging code must be fixed before merging. Once corrected, this will be a valuable improvement to error handling and data validation. Positive Aspects
Thank you for working on improving the robustness of the message handling code. The metadata validation is a great addition that will prevent subtle bugs. Please fix the syntax error and this will be ready to merge! |
Subhajitdas99
left a comment
There was a problem hiding this comment.
Thanks for the review!
Good catch on the syntax error in the structured logging block.
I've fixed the issue and pushed the update.
Please let me know if anything else needs adjustment.
Subhajitdas99
left a comment
There was a problem hiding this comment.
Summary
This PR fixes and enables the bindufy validation test suite which was previously skipped due to broken imports and monkeypatching.
Changes
- Correctly import the bindufy module for monkeypatching
- Restore bindufy function import for test execution
- Fix incorrect exception expectations in tests
- Remove global skip marker and enable validation tests
Result
All validation tests now run successfully:
12 passed in 1.15s
These tests verify required configuration validation for:
- author
- name
- deployment.url
This improves reliability of the agent configuration validation logic.
Summary
Improves metadata validation in MessageHandlers.
Changes
Verification