🐛 Bug Report: `langgraph_utils.extract_graph_structure` drops `gen_ai.workflow.nodes` when node ids are str subclasses

Open Beginner friendly
#4,447 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python

Research direction

Start in packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/langgraph_utils.py and run the provided StrEnum reproduction with a recording TracerProvider. Trace how node IDs reach the span attribute, then verify that gen_ai.workflow.nodes contains plain strings and that the OpenTelemetry warning is absent.

Written by the indexing model from the issue text.

Description

Which component is this bug for?

Langchain Instrumentation

📜 Description

LangGraph permits StrEnum node ids (graph.add_node(MyEnum.X, ...)). extract_graph_structure appends them raw (nodes.append(node_id)), and patch.py passes the list to set_attribute. OTel's _clean_attribute validates sequence elements with type(element) not in (bool, str, bytes, int, float). An exact-type check. So a str subclass is rejected, the entire gen_ai.workflow.nodes attribute is dropped, and opentelemetry.attributes logs a WARNING on every graph invocation.

👟 Reproduction steps
from enum import StrEnum
from typing import TypedDict

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter

# A recording TracerProvider is required, otherwise spans are no-ops
# and set_attribute never runs OTel's attribute validation.
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)

from opentelemetry.instrumentation.langchain import LangchainInstrumentor
LangchainInstrumentor().instrument()

from langgraph.graph import StateGraph, START, END


class NodeName(StrEnum):          # node ids are a str subclass
    PARSE = "parse"
    CLASSIFY = "classify"


class State(TypedDict):
    value: int


graph = StateGraph(State)
graph.add_node(NodeName.PARSE, lambda s: {"value": 1})       # StrEnum member as node id
graph.add_node(NodeName.CLASSIFY, lambda s: {"value": 2})
graph.add_edge(START, NodeName.PARSE)
graph.add_edge(NodeName.PARSE, NodeName.CLASSIFY)
graph.add_edge(NodeName.CLASSIFY, END)

graph.compile().invoke({"value": 0})
👍 Expected behavior

gen_ai.workflow.nodes should be populated with the node names as plain strings, with no warning. LangGraph officially allows StrEnum (and other str-subclass) node ids, so the instrumentation should record them the same way it records string ids.

👎 Actual Behavior with Screenshots
WARNING opentelemetry.attributes: Invalid type NodeName in attribute
'gen_ai.workflow.nodes' value sequence. Expected one of
['bool', 'str', 'bytes', 'int', 'float'] or None
🤖 Python Version

3.14

📃 Provide any additional context for the Bug.

Root cause seems to be in packages/opentelemetry-instrumentation-langchain/opentelemetry/instrumentation/langchain/langgraph_utils.py

👀 Have you spent some time to check if this bug has been raised before?
  • I checked and didn't find similar issue
Are you willing to submit PR?

None

Dominant language
Python
Stars
7.4k
Forks
1.1k
Avg merge
8d 14h
Merged PRs (30d)
2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from traceloop/openllmetry

All issues in traceloop/openllmetry

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.