Skip to content

core: fix trim_messages token_counter detection for lambdas and postponed annotations#35657

Closed
Alvin Tang (alvinttang) wants to merge 1 commit intolangchain-ai:masterfrom
alvinttang:fix/trim-messages-callable-counter
Closed

core: fix trim_messages token_counter detection for lambdas and postponed annotations#35657
Alvin Tang (alvinttang) wants to merge 1 commit intolangchain-ai:masterfrom
alvinttang:fix/trim-messages-callable-counter

Conversation

@alvinttang
Copy link
Copy Markdown

Description

Fixes a bug where trim_messages misclassifies per-message token_counter callables as per-list counters, causing AttributeError: 'list' object has no attribute 'content' at runtime.

Root cause

The detection logic used annotation is BaseMessage (identity check) to determine if token_counter accepts a single BaseMessage or a list. This fails for:

  • Lambdas — no annotation available
  • Unannotated functions — annotation is inspect.Parameter.empty
  • String annotations — annotation is a string like "BaseMessage", not the class
  • Subclass annotations — e.g. msg: HumanMessageHumanMessage is not BaseMessage
  • Postponed annotationsfrom __future__ import annotations turns all annotations into strings

Fix

Added a _is_per_message_counter() helper that:

  1. Uses typing.get_type_hints() to resolve string and postponed annotations
  2. Uses issubclass() instead of identity to handle subclass annotations
  3. Falls back to probing with a dummy message for lambdas and unannotated callables

Before

# All of these fail with AttributeError
trim_messages(messages, max_tokens=5, token_counter=lambda msg: len(msg.content.split()))
trim_messages(messages, max_tokens=5, token_counter=counter_no_annotation)
trim_messages(messages, max_tokens=5, token_counter=counter_with_subclass_annotation)

After

All forms work correctly, including len as a list counter.

Issue

Fixes #35629

Tests

Verified with the reproduction script from the issue — all five cases now pass. List counters (len, annotated list functions) continue to work correctly.

… subclasses, and postponed annotations

The per-message vs per-list token_counter detection in trim_messages
used `annotation is BaseMessage` (identity check), which failed for
lambdas, unannotated functions, string annotations, subclass
annotations (e.g. HumanMessage), and postponed annotations via
`from __future__ import annotations`.

Replace with a robust _is_per_message_counter() helper that:
1. Uses typing.get_type_hints() to resolve string/postponed annotations
2. Uses issubclass() instead of identity to handle subclass annotations
3. Falls back to probing with a dummy message for lambdas and
   unannotated callables

Fixes langchain-ai#35629
@github-actions github-actions bot added core `langchain-core` package issues & PRs external labels Mar 8, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Mar 8, 2026

Merging this PR will not alter performance

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

✅ 13 untouched benchmarks
⏩ 23 skipped benchmarks1


Comparing alvinttang:fix/trim-messages-callable-counter (d44e9cb) with master (29134dc)2

Open in CodSpeed

Footnotes

  1. 23 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on master (532b014) during the generation of this report, so 29134dc was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@gautamvarmadatla
Copy link
Copy Markdown

GAUTAM V DATLA (gautamvarmadatla) commented Mar 8, 2026

Hi! Creator of the issue here :)

Thanks for working on this. However, I already have a PR open to fix it from when I originally opened the issue. Plelase try to avoid duplicates

Copy link
Copy Markdown
Collaborator

@ccurme ccurme (ccurme) left a comment

Choose a reason for hiding this comment

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

Duplicated with #35630.

@gambletan
Copy link
Copy Markdown
Contributor

Sorry about this — I should have checked for existing PRs before submitting. I didn't realize you already had #35630 open for the same issue. Won't happen again. Thanks for the fix!

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

Labels

core `langchain-core` package issues & PRs external

Projects

None yet

Development

Successfully merging this pull request may close these issues.

trim_messages breaks when token_counter is a per-message callable (lambda, subclass annotation, or postponed annotations)

4 participants