Skip to content

Conversation

@le-codeur-rapide
Copy link
Contributor

Hello everyone !
While reading the code of libs/langgraph/langgraph/channels/binop.py, I found out that the helper function _strip_extras may have a small typo:

# Adapted from typing_extensions
def _strip_extras(t):  # type: ignore[no-untyped-def]
    """Strips Annotated, Required and NotRequired from a given type."""
    if hasattr(t, "__origin__"):
        return _strip_extras(t.__origin__)
    if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired):
        return _strip_extras(t.__args__[0])

    return t

There is an issue because the second part of the function will never be reached because if hasattr(t, "__origin__") == False then hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired) == False too.

The original implementation from typing_extension is github link :

  def _strip_extras(t):
      """Strips Annotated, Required and NotRequired from a given type."""
      if isinstance(t, typing._AnnotatedAlias):
          return _strip_extras(t.__origin__)
      if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired, ReadOnly):
          return _strip_extras(t.__args__[0])
      # Other cases...

We can see that they don't use hasattr(t, "__origin__") as first condition but isinstance(t, typing._AnnotatedAlias) which specifically targets annotations.

This code was introduced in this commit. According to the docstring of the function, the first two lines are supposed to target the annotations specifically but I am not 100% certain that changing if hasattr(t, "__origin__"): to if isinstance(t, typing._AnnotatedAlias): will not break other parts of the code (moreover there might be a reason the author of this commit made that choice.).
But switching the two ifs seams to fix the function behaviour without breaking any existing code, this is why I propose this small fix.

Sample code for the bug

We can exhibit the bug when manipulating the BinaryOperatorAggregate object:

from typing import Required
import operator
from langgraph.channels.binop import BinaryOperatorAggregate

agg = BinaryOperatorAggregate(Required[list[int]], operator.add)
agg.value.append(1)

returns
AttributeError: 'object' object has no attribute 'append'

But

from typing import Required
import operator
from langgraph.channels.binop import BinaryOperatorAggregate

agg = BinaryOperatorAggregate(list[int], operator.add)
agg.value.append(1)

works fine.

Higher level object manipulation

It looks like this code has no impact over higher level objects because the BinaryOperatorAggregate values are always updated via the update() method that will handle MISSING flag. the BinaryOperatorAggregate(...).value is never assigned directly in the code.

second if would never be reached
@vercel
Copy link

vercel bot commented Nov 10, 2025

@le-codeur-rapide is attempting to deploy a commit to the LangChain Team on Vercel.

A member of the Team first needs to authorize it.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant