From 0f72e91b572022386f7bc2aed41e427fc900ab13 Mon Sep 17 00:00:00 2001 From: edbyford Date: Fri, 27 Feb 2026 11:57:22 +0000 Subject: [PATCH] fix: coerce NaN to None for optional string fields in TransactionObject When the Lunch Money API returns null for optional string fields (category_name, recurring_payee, recurring_cadence, recurring_type, recurring_currency, recurring_description), these can arrive as NaN floats rather than None, causing Pydantic validation to fail. This adds a field_validator that coerces NaN values to None, similar to the fix applied in #113 for the Assets model. Fixes #146 Co-Authored-By: Claude Opus 4.6 --- lunchable/models/transactions.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lunchable/models/transactions.py b/lunchable/models/transactions.py index 72ce663b..35faca44 100644 --- a/lunchable/models/transactions.py +++ b/lunchable/models/transactions.py @@ -6,6 +6,7 @@ import datetime import logging +import math from enum import Enum from typing import Any, Dict, List, Optional, Union @@ -301,6 +302,21 @@ class TransactionObject(TransactionBaseObject): None, description=_TransactionDescriptions.children ) + @field_validator( + "category_name", + "recurring_payee", + "recurring_cadence", + "recurring_type", + "recurring_currency", + "recurring_description", + mode="before", + ) + def coerce_nan_to_none(cls, v: Any) -> Optional[str]: + """Coerce NaN float values to None for optional string fields.""" + if isinstance(v, float) and math.isnan(v): + return None + return v + @field_validator("plaid_metadata", mode="before") def to_json(cls, x: Optional[str]) -> Optional[Dict[str, Any]]: """