litellm - ✅(Solved) Fix [Bug]: langfuse_otel set_messages crashes on litellm.Message objects (Object of type Message is not JSON serializable) [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#26977Fetched 2026-05-02 05:28:13
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×2cross-referenced ×1

Error Message

LiteLLM:ERROR: _utils.py:415 - [Arize/Phoenix] Failed to set OpenInference span attributes: Object of type Message is not JSON serializable

Root Cause

Root cause: LangfuseLLMObsOTELAttributes.set_messages does json.dumps({"messages": kwargs.get("messages"), ...}) directly. litellm.Message is a pydantic v2 model and is not JSON-serializable by default — json.dumps raises TypeError, and arize._utils.set_attributes catches and logs the error.

Fix Action

Fixed

PR fix notes

PR #26978: fix(langfuse_otel): serialize pydantic Message objects in set_messages

Description (problem / solution / changelog)

Fixes #26977. Refs #13672.

Problem

LangfuseLLMObsOTELAttributes.set_messages does json.dumps({\"messages\": kwargs.get(\"messages\"), ...}) directly. When the caller passes list[litellm.Message] — a documented public API surface (litellm.Message) — json.dumps raises TypeError: Object of type Message is not JSON serializable, the OpenInference attribute setter bails, and every LLM call spams:

LiteLLM:ERROR: _utils.py:415 - [Arize/Phoenix] Failed to set OpenInference span attributes: Object of type Message is not JSON serializable

Beyond the noise, the failure has real telemetry impact: the trace is still exported but with the input payload missing, and the span's kind is degraded from GENERATION to a generic span (the OPENINFERENCE_SPAN_KIND attribute is set later in the same try/except in arize/_utils.set_attributes, so it gets skipped along with set_messages when the latter raises).

Fix

set_messages now normalises pydantic objects to dicts via .model_dump() before json.dumps. Plain-dict messages keep working unchanged — only the previously-broken pydantic path is touched.

raw_messages = kwargs.get(\"messages\") or []
messages = [
    m.model_dump() if hasattr(m, \"model_dump\") else m
    for m in raw_messages
]
prompt: Dict[str, Any] = {\"messages\": messages}

Tests

Two new tests in tests/test_litellm/integrations/test_langfuse_otel.py:

  • test_set_messages_handles_pydantic_message_objects — passing list[litellm.Message] no longer raises and the dumped JSON contains the expected role/content fields.
  • test_set_messages_passes_through_plain_dicts — the existing dict path still works.
$ pytest tests/test_litellm/integrations/test_langfuse_otel.py
22 passed

End-to-end verification

Reproduced and verified against a self-hosted Langfuse instance with bedrock/jp.anthropic.claude-haiku-4-5-20251001-v1:0:

beforeafter
[Arize/Phoenix] Failed ... logevery LLM callgone
Langfuse observation inputemptyfull message list
Langfuse observation kindTOOL (fallback)GENERATION
Trace exportsucceedssucceeds

Verified by querying /api/public/traces/{id} after each call.

Out of scope

The same json.dumps(messages) pattern exists in weave/weave_otel.py, and a related-but-distinct issue (.get() against pydantic objects) exists in arize/_utils.py. Both have different fix shapes and are kept separate. Happy to file follow-ups if useful.

Changed files

  • litellm/integrations/langfuse/langfuse_otel_attributes.py (modified, +13/-1)
  • tests/test_litellm/integrations/test_langfuse_otel.py (modified, +60/-0)

Code Example

LiteLLM:ERROR: _utils.py:415 - [Arize/Phoenix] Failed to set OpenInference span attributes: Object of type Message is not JSON serializable

---

import litellm
from litellm import Message

litellm.success_callback = ["langfuse_otel"]
litellm.failure_callback = ["langfuse_otel"]
# Set LANGFUSE_HOST + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY
# Any provider works; the error is independent of the model.

litellm.completion(
    model="bedrock/jp.anthropic.claude-haiku-4-5-20251001-v1:0",
    messages=[Message(role="user", content="hi")],   # <- pydantic Message, not dict
    max_tokens=4,
)
# stderr: [Arize/Phoenix] Failed to set OpenInference span attributes:
#         Object of type Message is not JSON serializable

---

import json
from litellm.types.utils import Message
json.dumps([Message(role="user", content="hi")])
# TypeError: Object of type Message is not JSON serializable

---

LiteLLM:ERROR: _utils.py:415 - [Arize/Phoenix] Failed to set OpenInference span attributes: Object of type Message is not JSON serializable
Traceback (most recent call last):
  File ".../litellm/integrations/arize/_utils.py", line 413, in set_attributes
    attributes.set_messages(span, kwargs)
  File ".../litellm/integrations/langfuse/langfuse_otel_attributes.py", line 99, in set_messages
    safe_set_attribute(span, "langfuse.observation.input", json.dumps(input))
TypeError: Object of type Message is not JSON serializable

---

raw_messages = kwargs.get("messages") or []
messages = [
    m.model_dump() if hasattr(m, "model_dump") else m
    for m in raw_messages
]
prompt = {"messages": messages}
...
safe_set_attribute(span, "langfuse.observation.input", json.dumps(prompt))
RAW_BUFFERClick to expand / collapse

Check for existing issues

I searched and found #13672 (the meta-bug for langfuse_otel pulling in Arize/Phoenix attribute setters). This issue is one specific instance of that family — set_messages choking on pydantic Message objects — that hasn't been filed or fixed.

What happened?

When langfuse_otel is registered as a callback and the caller passes messages=list[litellm.Message] (a documented public API exposed via the top-level litellm.Message export), every LLM call logs:

LiteLLM:ERROR: _utils.py:415 - [Arize/Phoenix] Failed to set OpenInference span attributes: Object of type Message is not JSON serializable

The trace is still exported, but the input payload is dropped from the span and the span kind is degraded from GENERATION to a generic span (the OPENINFERENCE_SPAN_KIND attribute is set later in the same try/except block, so it gets skipped along with set_messages when the latter raises).

Root cause: LangfuseLLMObsOTELAttributes.set_messages does json.dumps({"messages": kwargs.get("messages"), ...}) directly. litellm.Message is a pydantic v2 model and is not JSON-serializable by default — json.dumps raises TypeError, and arize._utils.set_attributes catches and logs the error.

Steps to Reproduce

import litellm
from litellm import Message

litellm.success_callback = ["langfuse_otel"]
litellm.failure_callback = ["langfuse_otel"]
# Set LANGFUSE_HOST + LANGFUSE_PUBLIC_KEY + LANGFUSE_SECRET_KEY
# Any provider works; the error is independent of the model.

litellm.completion(
    model="bedrock/jp.anthropic.claude-haiku-4-5-20251001-v1:0",
    messages=[Message(role="user", content="hi")],   # <- pydantic Message, not dict
    max_tokens=4,
)
# stderr: [Arize/Phoenix] Failed to set OpenInference span attributes:
#         Object of type Message is not JSON serializable

Minimal isolated repro (no network):

import json
from litellm.types.utils import Message
json.dumps([Message(role="user", content="hi")])
# TypeError: Object of type Message is not JSON serializable

Relevant log output

LiteLLM:ERROR: _utils.py:415 - [Arize/Phoenix] Failed to set OpenInference span attributes: Object of type Message is not JSON serializable
Traceback (most recent call last):
  File ".../litellm/integrations/arize/_utils.py", line 413, in set_attributes
    attributes.set_messages(span, kwargs)
  File ".../litellm/integrations/langfuse/langfuse_otel_attributes.py", line 99, in set_messages
    safe_set_attribute(span, "langfuse.observation.input", json.dumps(input))
TypeError: Object of type Message is not JSON serializable

What part of LiteLLM is this about?

SDK (litellm Python package)

What LiteLLM version are you on?

Reproduced on 1.83.14. Code path is unchanged on main (1.84.0).

Proposed fix

langfuse_otel_attributes.py — convert pydantic models to dicts via .model_dump() before json.dumps. Plain-dict messages keep working unchanged.

raw_messages = kwargs.get("messages") or []
messages = [
    m.model_dump() if hasattr(m, "model_dump") else m
    for m in raw_messages
]
prompt = {"messages": messages}
...
safe_set_attribute(span, "langfuse.observation.input", json.dumps(prompt))

PR follows.

Notes

The same json.dumps(messages) pattern exists in weave/weave_otel.py, and a related-but-distinct bug (.get() against pydantic objects) exists in arize/_utils.py. Both are out of scope for this PR — happy to file separately if useful.

extent analysis

TL;DR

The issue can be fixed by converting pydantic models to dictionaries using the model_dump() method before attempting to JSON serialize them.

Guidance

  • The root cause of the issue is the attempt to JSON serialize pydantic models directly, which are not JSON serializable by default.
  • To fix this, convert pydantic models to dictionaries using the model_dump() method before passing them to json.dumps().
  • The proposed fix involves modifying the langfuse_otel_attributes.py file to convert pydantic models to dictionaries before JSON serialization.
  • Verify the fix by checking that the error message is no longer logged and that the input payload is correctly included in the span.

Example

raw_messages = kwargs.get("messages") or []
messages = [
    m.model_dump() if hasattr(m, "model_dump") else m
    for m in raw_messages
]
prompt = {"messages": messages}
safe_set_attribute(span, "langfuse.observation.input", json.dumps(prompt))

Notes

  • This fix only addresses the issue in langfuse_otel_attributes.py and does not fix similar issues in other files, such as weave/weave_otel.py or arize/_utils.py.
  • Additional PRs may be needed to fix these related issues.

Recommendation

Apply the proposed workaround by converting pydantic models to dictionaries using the model_dump() method before JSON serialization, as this fixes the immediate issue and allows for correct logging and span creation.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

litellm - ✅(Solved) Fix [Bug]: langfuse_otel set_messages crashes on litellm.Message objects (Object of type Message is not JSON serializable) [1 pull requests, 1 participants]