Skip to content

Navigation Menu

Sign in
Sign up

fix: serialize NaN/Inf floats nested in pydantic models as JSON-safe strings - #1817

Open
uuzzrm wants to merge 1 commit into
langfuse:main from
uuzzrm:fix/serialize-nan-in-pydantic-models
Open

fix: serialize NaN/Inf floats nested in pydantic models as JSON-safe strings #1817
uuzzrm wants to merge 1 commit into
langfuse:main from
uuzzrm:fix/serialize-nan-in-pydantic-models

Conversation

@uuzzrm

@uuzzrm uuzzrm commented Aug 15, 2026
edited by greptile-apps Bot
Loading

Copy link
Copy Markdown

What does this PR do?

Fixes #16048

EventSerializer's BaseModel branch returned obj.model_dump() directly, so non-finite floats nested inside a pydantic model bypassed the NaN/Inf sanitizer that the dict/list branches already apply. Python's JSON C encoder then emitted bare NaN/Infinity tokens, which strict JSON parsers reject. On the tracing path, any traced pydantic object carrying a NaN/Inf float (common with ML/scoring payloads) produced an event body that failed ingestion.

The fix routes the dumped dict back through default(), so the same sanitization applies at every nesting depth:

from pydantic import BaseModel
from langfuse._utils.serializer import EventSerializer
class Scores(BaseModel):
 confidence: float
# before: {"confidence": NaN} (bare NaN, invalid JSON)
# after: {"confidence": "NaN"}
EventSerializer().encode(Scores(confidence=float("nan")))

Type of change

  • Bug fix

Verification

pytest tests/unit/test_serializer.py -q -k "not path" # 29 passed
ruff check langfuse/_utils/serializer.py tests/unit/test_serializer.py # all checks passed
ruff format --check langfuse/_utils/serializer.py tests/unit/test_serializer.py

The new regression test test_pydantic_model_with_non_finite_float_serializes_to_valid_json fails before the fix (strict parse raises ValueError: NaN) and passes after. test_path fails on this machine only (POSIX-vs-Windows path separators) and passes in CI's Linux runner; the same pre-existing mypy import-not-found note for langchain_core is present on the unmodified file.

Checklist

  • I self-reviewed the diff using code_review.md.
  • I added or updated tests for behavior changes.
  • I updated docs, examples, or .env.template if needed.
  • I did not hand-edit generated files; if generated files changed, I used the upstream regeneration path.
  • I did not commit secrets or credentials.

Greptile Summary

Routes Pydantic model_dump() output back through EventSerializer so nested non-finite floats become JSON-safe strings.

  • Sanitizes nested NaN and infinity values consistently with existing dict/list handling.
  • Adds regression coverage using strict JSON parsing for Pydantic payloads.

Confidence Score: 5/5

The PR appears safe to merge, with the intended Pydantic serialization behavior covered by a focused strict-JSON regression test.

The changed branch reuses the established recursive normalization path, ensuring non-finite floats nested in Pydantic models no longer produce invalid bare JSON constants, and no concrete blocking or non-blocking defect remains.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
 A[Pydantic BaseModel] --> B[model_dump]
 B --> C[EventSerializer recursive normalization]
 C --> D[NaN and Infinity converted to strings]
 D --> E[Valid JSON ingestion payload]
Loading

Reviews (1): Last reviewed commit: "fix: serialize NaN/Inf floats nested in ..." | Re-trigger Greptile

Context used:

greptile-apps[bot] reacted with thumbs up emoji
...strings
The BaseModel branch of EventSerializer returned model_dump() directly,
so non-finite floats nested inside a pydantic model bypassed the NaN/Inf
sanitizer that the dict/list branches apply. The JSON C encoder then
emitted bare NaN/Infinity tokens, which strict JSON parsers reject -- a
traced pydantic object carrying a NaN/Inf float produced an event body
that failed ingestion. Route the dumped dict back through default() so
the same sanitization applies at every nesting depth.
Fixes #16048.
Signed-off-by: Ruiming Zhao <uuzzrm@gmail.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@claude claude[bot] claude[bot] left review comments

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

AltStyle によって変換されたページ (->オリジナル) /