Skip to content

core: BaseChatModel.agenerate masks a non-Exception BaseException with AttributeError #38469

Description

Submission checklist

  • 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-openrouter
  • langchain-perplexity
  • langchain-qdrant
  • langchain-xai
  • Other / not sure / general

Related Issues / PRs

No response

Reproduction Steps / Example Code (Python)

import asyncio
from typing import Any

from langchain_core.callbacks import AsyncCallbackHandler
from langchain_core.language_models import BaseChatModel
from langchain_core.messages import HumanMessage
from langchain_core.outputs import ChatResult


class Abort(BaseException):
    """A BaseException that is NOT an Exception (e.g., CancelledError )."""


class RaisingModel(BaseChatModel):
    @property
    def _llm_type(self) -> str:
        return "raising"

    def _generate(self, *args: Any, **kwargs: Any) -> ChatResult:
        raise Abort

    async def _agenerate(self, *args: Any, **kwargs: Any) -> ChatResult:
        raise Abort


async def main() -> None:
    model = RaisingModel()
    # Attaching any callback makes run_managers truthy and triggers the on_llm_end path.
    await model.agenerate([[HumanMessage("hi")]], callbacks=[AsyncCallbackHandler()])


asyncio.run(main())

Error Message and Stack Trace (if applicable)

generations=[res.generations],  # type: ignore[union-attr]                                                                                                                                                 
                   ^^^^^^^^^^^^^^^                                                                                                                                                                               
  AttributeError: 'Abort' object has no attribute 'generations'

Description

BaseChatModel.agenerate runs its per-message generations with asyncio.gather(..., return_exceptions=True). It collects failed results with an isinstance(res, BaseException) check, but the subsequent on_llm_end step filters results with the narrower isinstance(res, Exception).

As a result, a BaseException that is not an ExceptionKeyboardInterrupt, asyncio.CancelledError, or a library's blocking/abort sentinel — slips past the on_llm_end filter. The cleanup code then reads .generations off the raised exception object and raises AttributeError, which masks the original exception. The user sees a confusing attribute error instead of the cancellation/interrupt/abort that actually occurred.

The two checks should agree on BaseException. This has been detailed and/or worked around in two different ddtrace PRs:

System Info

Package Information

langchain_core: 1.4.8
langsmith: 0.8.18
langchain_protocol: 0.0.17
langchain_tests: 1.1.9

Optional packages not installed

deepagents
deepagents-cli

Other Dependencies

httpx: 0.28.1 > pytest-socket: 0.7.0
jsonpatch: 1.33 > pyyaml: 6.0.3
numpy: 2.3.5 > requests: 2.33.0
orjson: 3.11.6 > requests-toolbelt: 1.0.0
packaging: 26.0 > rich: 14.2.0
pydantic: 2.12.5 > syrupy: 5.1.0
pytest: 9.0.3 > tenacity: 9.1.4
pytest-asyncio: 1.3.0 > typing-extensions: 4.15.0
pytest-benchmark: 5.2.3> uuid-utils: 0.16.0
pytest-codspeed: 4.3.0 > vcrpy: 8.2.1
pytest-recording: 0.13.4> websockets: 16.0
pytest-socket: 0.7.0 > wrapt: 2.0.1
> xxhash: 3.6.0
> zstandard: 0.25.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugRelated to a bug, vulnerability, unexpected error with an existing featureexternallangchain`langchain` package issues & PRs

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions