langchain - ✅(Solved) Fix RecursionError in _filter_injected_args when args_schema is a dict (JSON Schema) [4 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
langchain-ai/langchain#35258Fetched 2026-04-08 00:26:56
View on GitHub
Comments
0
Participants
1
Timeline
10
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×4labeled ×3closed ×1issue_type_added ×1

When args_schema is a dict (JSON Schema format) instead of a Pydantic BaseModel, the _filter_injected_args method at line 824 calls get_all_basemodel_annotations(self.args_schema).

The get_all_basemodel_annotations function expects a class/type, but receives a dict instance:

isinstance(dict_instance, type) → False (a dict instance is not a type)

Falls to else branch at line 1497

get_origin(dict_instance) → None

Recursively calls get_all_basemodel_annotations(None, ...)

None is also not a type, so it recurses infinitely

Impact: This affects MCP (Model Context Protocol) tool integration via langchain-mcp-adapters, which passes tool.inputSchema (a dict) directly as args_schema to StructuredTool. Every tool invocation logs this RecursionError, causing significant log spam in production environments.

The tool still functions because the exception is caught, but the error is logged on every single tool call.

Suggested Fix

Add a type check before calling get_all_basemodel_annotations in _filter_injected_args:

In _filter_injected_args (around line 821-824)

if self.args_schema is not None and not isinstance(self.args_schema, dict): try: annotations = get_all_basemodel_annotations(self.args_schema) for field_name, field_type in annotations.items(): if _is_injected_arg_type(field_type): filtered_keys.add(field_name) except Exception: _logger.debug( "Failed to get args_schema annotations for filtering.", exc_info=True, )

Error Message

import logging import sys

Enable DEBUG logging to see the caught exception

logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)

from langchain_core.tools import StructuredTool

When args_schema is a dict (JSON Schema) instead of a Pydantic BaseModel:

tool = StructuredTool( name="example_tool", description="Example tool", func=lambda x: x, args_schema={"type": "object", "properties": {"x": {"type": "string"}}} )

Invoking the tool triggers the error (caught internally)

result = tool.invoke({"x": "test"}) print(f"Result: {result}")

Root Cause

The tool still functions because the exception is caught, but the error is logged on every single tool call.

Fix Action

Fix / Workaround

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

PR fix notes

PR #35260: fix(core): prevent recursion error when args_schema is dict

Description (problem / solution / changelog)

fix(core): prevent recursion error when args_schema is dict

Fixes #35258 Added type check in _filter_injected_args to skip annotation filtering when args_schema is a dict (JSON Schema) instead of a Pydantic BaseModel. This prevents infinite recursion in get_all_basemodel_annotations which was causing RecursionError logs on every tool invocation for MCP-integrated tools.

Changes:

  • Added isinstance(self.args_schema, dict) check before calling get_all_basemodel_annotations
  • Added regression test test_tool_with_dict_args_schema to verify dict args_schema works correctly

Testing:

  • All existing tests pass (161 passed)
  • New test verifies tools with dict args_schema invoke successfully
  • Verified original reproduction case no longer logs RecursionError

Social handles

LinkedIn: https://www.linkedin.com/in/karthik-reddy-jannupalli/

Changed files

  • libs/core/langchain_core/tools/base.py (modified, +2/-1)
  • libs/core/tests/unit_tests/test_tools.py (modified, +5/-1)

PR #35262: fix: RecursionError when initializing StructuredTool with dict schema

Description (problem / solution / changelog)

Fixes #35258

Description

This PR fixes a RecursionError that occurred when initializing a StructuredTool with a dictionary args_schema (JSON Schema) instead of a Pydantic BaseModel.

Changes

  • Modified in to check if is a BaseModel subclass before calling
  • Added regression test to prevent future regressions

Testing

  • All existing tests pass (161 passed)
  • New regression test verifies the fix

Changed files

  • libs/core/langchain_core/tools/base.py (modified, +5/-1)
  • libs/core/tests/unit_tests/test_tools.py (modified, +26/-0)

PR #35286: fix(core): handle dict args_schema in injected arg filtering

Description (problem / solution / changelog)

Fixes #35258

This updates injected-arg filtering to skip BaseModel annotation introspection when args_schema is provided as a JSON Schema dict, which avoids the recursion/log-spam path while preserving existing filtering behaviour.

Added a regression test for StructuredTool with dict args_schema to verify invocation still works and no annotation-failure debug log is emitted.

No breaking API changes.

Verification:

  • ruff check libs/core/langchain_core/tools/base.py libs/core/tests/unit_tests/test_tools.py
  • python -m pytest libs/core/tests/unit_tests/test_tools.py -k "filter_injected_args" -q (5 passed)

Changed files

  • libs/core/langchain_core/tools/base.py (modified, +1/-1)
  • libs/core/tests/unit_tests/test_tools.py (modified, +28/-0)

PR #35291: fix(core): fix RecursionError in _filter_injected_args when args_schema is a dict

Description (problem / solution / changelog)

Description

Fixes #35258.

When args_schema is a plain dict (JSON Schema) instead of a Pydantic BaseModel, calling get_all_basemodel_annotations() on it causes a RecursionError. While the existing try/except catches this, it generates noisy debug logs and is unnecessary since dict schemas cannot have injected args.

Changes

Added not isinstance(self.args_schema, dict) guard before attempting to extract annotations, consistent with other dict-schema checks already in the codebase (e.g., lines 574, 593).

Testing

from langchain_core.tools import StructuredTool
tool = StructuredTool(
    name="example", description="Example", func=lambda x: x,
    args_schema={"type": "object", "properties": {"x": {"type": "string"}}}
)
tool.invoke({"x": "test"})  # no more RecursionError in debug logs

Changed files

  • libs/core/langchain_core/tools/base.py (modified, +4/-2)

Code Example

import logging 
import sys 
 
# Enable DEBUG logging to see the caught exception 
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) 
 
from langchain_core.tools import StructuredTool 
 
# When args_schema is a dict (JSON Schema) instead of a Pydantic BaseModel: 
tool = StructuredTool( 
   name="example_tool", 
   description="Example tool", 
   func=lambda x: x, 
   args_schema={"type": "object", "properties": {"x": {"type": "string"}}} 
) 
 
# Invoking the tool triggers the error (caught internally) 
result = tool.invoke({"x": "test"}) 
print(f"Result: {result}")

---

langchain_core.tools.base - DEBUG - Failed to get args_schema annotations for filtering. 
Traceback (most recent call last): 
 File ".../langchain_core/tools/base.py", line 824, in _filter_injected_args 
   annotations = get_all_basemodel_annotations(self.args_schema) 
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
 File ".../langchain_core/tools/base.py", line 1498, in get_all_basemodel_annotations 
   annotations = get_all_basemodel_annotations( 
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
 File ".../langchain_core/tools/base.py", line 1498, in get_all_basemodel_annotations 
   annotations = get_all_basemodel_annotations( 
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
 [Previous line repeated 992 more times] 
RecursionError: maximum recursion depth exceeded
RAW_BUFFERClick to expand / collapse

Checked other resources

  • This is a bug, not a usage question.
  • I added a clear and descriptive title that summarizes this issue.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangChain rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
  • This is not related to the langchain-community package.
  • I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.

Package (Required)

  • langchain
  • langchain-openai
  • langchain-anthropic
  • langchain-classic
  • langchain-core
  • langchain-model-profiles
  • langchain-tests
  • langchain-text-splitters
  • langchain-chroma
  • langchain-deepseek
  • langchain-exa
  • langchain-fireworks
  • langchain-groq
  • langchain-huggingface
  • langchain-mistralai
  • langchain-nomic
  • langchain-ollama
  • langchain-perplexity
  • langchain-qdrant
  • langchain-xai
  • Other / not sure / general

Related Issues / PRs

Reproduction Steps / Example Code (Python)

import logging 
import sys 
 
# Enable DEBUG logging to see the caught exception 
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) 
 
from langchain_core.tools import StructuredTool 
 
# When args_schema is a dict (JSON Schema) instead of a Pydantic BaseModel: 
tool = StructuredTool( 
   name="example_tool", 
   description="Example tool", 
   func=lambda x: x, 
   args_schema={"type": "object", "properties": {"x": {"type": "string"}}} 
) 
 
# Invoking the tool triggers the error (caught internally) 
result = tool.invoke({"x": "test"}) 
print(f"Result: {result}")

Error Message and Stack Trace (if applicable)

langchain_core.tools.base - DEBUG - Failed to get args_schema annotations for filtering. 
Traceback (most recent call last): 
 File ".../langchain_core/tools/base.py", line 824, in _filter_injected_args 
   annotations = get_all_basemodel_annotations(self.args_schema) 
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
 File ".../langchain_core/tools/base.py", line 1498, in get_all_basemodel_annotations 
   annotations = get_all_basemodel_annotations( 
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
 File ".../langchain_core/tools/base.py", line 1498, in get_all_basemodel_annotations 
   annotations = get_all_basemodel_annotations( 
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
 [Previous line repeated 992 more times] 
RecursionError: maximum recursion depth exceeded

Description

When args_schema is a dict (JSON Schema format) instead of a Pydantic BaseModel, the _filter_injected_args method at line 824 calls get_all_basemodel_annotations(self.args_schema).

The get_all_basemodel_annotations function expects a class/type, but receives a dict instance:

isinstance(dict_instance, type) → False (a dict instance is not a type)

Falls to else branch at line 1497

get_origin(dict_instance) → None

Recursively calls get_all_basemodel_annotations(None, ...)

None is also not a type, so it recurses infinitely

Impact: This affects MCP (Model Context Protocol) tool integration via langchain-mcp-adapters, which passes tool.inputSchema (a dict) directly as args_schema to StructuredTool. Every tool invocation logs this RecursionError, causing significant log spam in production environments.

The tool still functions because the exception is caught, but the error is logged on every single tool call.

Suggested Fix

Add a type check before calling get_all_basemodel_annotations in _filter_injected_args:

In _filter_injected_args (around line 821-824)

if self.args_schema is not None and not isinstance(self.args_schema, dict): try: annotations = get_all_basemodel_annotations(self.args_schema) for field_name, field_type in annotations.items(): if _is_injected_arg_type(field_type): filtered_keys.add(field_name) except Exception: _logger.debug( "Failed to get args_schema annotations for filtering.", exc_info=True, )

System Info

langchain-core: 1.2.13 (also tested on 1.2.11 - same issue) langchain: 1.2.10 langchain-mcp-adapters: 0.2.1 Python: 3.12 Platform: Linux

extent analysis

Fix Plan

1. Add Type Check in _filter_injected_args

  • In langchain_core/tools/base.py, modify the _filter_injected_args method to include a type check before calling get_all_basemodel_annotations:

if self.args_schema is not None and not isinstance(self.args_schema, dict): try: annotations = get_all_basemodel_annotations(self.args_schema) for field_name, field_type in annotations.items(): if _is_injected_arg_type(field_type): filtered_keys.add(field_name) except Exception: _logger.debug( "Failed to get args_schema annotations for filtering.", exc_info=True, ) else: # Handle dict case as before


#### 2. Update `langchain-core` to Latest Version

*   Update `langchain-core` to the latest version (1.2.14 or later) to ensure you have the latest bug fixes.

#### 3. Verify Fix

*   Run the reproduction steps/example code again to verify that the fix resolves the issue.
*   Check the logs to ensure that the RecursionError is no longer logged.

### Verification

*   Run the reproduction steps/example code with the updated `langchain-core` version.
*   Verify that the tool invocation completes successfully without logging the RecursionError.
*   Check the logs to ensure that the fix has resolved the issue.

### Extra Tips

*   Always check the latest version of `langchain-core` to ensure you have the latest bug fixes.
*   Consider adding additional logging or error handling to provide more context in case of future issues.

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

langchain - ✅(Solved) Fix RecursionError in _filter_injected_args when args_schema is a dict (JSON Schema) [4 pull requests, 1 participants]