diff --git a/backend/services/usage_metrics_service.py b/backend/services/usage_metrics_service.py index 8b1e09ba6..80297d2d3 100644 --- a/backend/services/usage_metrics_service.py +++ b/backend/services/usage_metrics_service.py @@ -297,7 +297,9 @@ def _extract_execution_result( if consensus_data is not None and consensus_data.leader_receipt: first_receipt = consensus_data.leader_receipt[0] if first_receipt is not None: - execution_result = getattr(first_receipt, "execution_result", None) + execution_result = self._receipt_field( + first_receipt, "execution_result" + ) if execution_result is not None: # Handle both enum and string values if hasattr(execution_result, "value"): diff --git a/tests/unit/test_bug_hunt_v0_123_dev.py b/tests/unit/test_bug_hunt_v0_123_dev.py new file mode 100644 index 000000000..39c536cde --- /dev/null +++ b/tests/unit/test_bug_hunt_v0_123_dev.py @@ -0,0 +1,18 @@ +from types import SimpleNamespace + +from backend.services.usage_metrics_service import UsageMetricsService + + +def test_usage_metrics_preserves_error_from_serialized_leader_receipt(): + """Finalization metrics must not turn a VM error into a successful decision.""" + consensus_data = SimpleNamespace( + leader_receipt=[{"execution_result": "ERROR"}], + ) + + result = UsageMetricsService()._extract_execution_result( + finalization_data={}, + consensus_data=consensus_data, + consensus_history=None, + ) + + assert result == "error"