From f5be3286137b6c47b4ef8b205e36b2f7cb7d6f1d Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Wed, 21 May 2025 12:17:48 +0100 Subject: [PATCH 1/2] Handle typeerror --- api/core/models.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/api/core/models.py b/api/core/models.py index 89904bf80068..01db00e92a0c 100644 --- a/api/core/models.py +++ b/api/core/models.py @@ -83,8 +83,11 @@ class _BaseHistoricalModel(models.Model): class Meta: abstract = True - def get_change_details(self) -> typing.Optional[typing.List[ModelChange]]: # type: ignore[return] - if self.history_type == "~": # type: ignore[attr-defined] + def get_change_details(self) -> typing.List[ModelChange]: + # Note that self.prev_record should never be None when self.history_type == "~" but we have + # seen rare cases in Sentry which cause an unhandled exception, so we instead handle the case + # and fall back to just return an empty list. + if self.history_type == "~" and self.prev_record is not None: # type: ignore[attr-defined] return [ change for change in self.diff_against(self.prev_record).changes # type: ignore[attr-defined] @@ -96,11 +99,10 @@ def get_change_details(self) -> typing.Optional[typing.List[ModelChange]]: # ty for key, value in self.instance.to_dict().items() # type: ignore[attr-defined] if key not in self._change_details_excluded_fields # type: ignore[attr-defined] ] - elif self.history_type == "-": # type: ignore[attr-defined] - # Ignore deletes because they get painful due to cascade deletes - # Maybe we can resolve this in the future but for now it's not - # critical. - return [] + + # Note that we ignore deletes because they get painful due to cascade deletes. Maybe we can + # resolve this in the future but for now it's not critical. + return [] def base_historical_model_factory( From ba588c18f3736848d21060c70ac0868da082da43 Mon Sep 17 00:00:00 2001 From: Matthew Elwell Date: Thu, 22 May 2025 11:25:24 +0100 Subject: [PATCH 2/2] Handle keyerror when sending invalid payload to update / create multivariate feature states --- api/features/serializers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/features/serializers.py b/api/features/serializers.py index 83224e4723eb..3af9219caaf3 100644 --- a/api/features/serializers.py +++ b/api/features/serializers.py @@ -567,7 +567,7 @@ def validate(self, attrs): # type: ignore[no-untyped-def] ) mv_values = attrs.get("multivariate_feature_state_values", []) - if sum([v["percentage_allocation"] for v in mv_values]) > 100: + if sum([v.get("percentage_allocation", 0) for v in mv_values]) > 100: raise serializers.ValidationError( "Multivariate percentage values exceed 100%." )