langchain-ai/langchain · error · OutputParserException

Unsupported model version for PydanticOutputParser: {self.py

Error message

Unsupported model version for PydanticOutputParser: {self.pydantic_object.__class__}

What it means

Defensive unreachable branch in PydanticOutputParser._parse_obj: pydantic_object is neither a pydantic v2 BaseModel nor a pydantic.v1 BaseModel subclass, so neither model_validate nor parse_obj applies. The type system normally prevents this; it fires only when a non-BaseModel leaks in past type checks.

Source

Thrown at libs/core/langchain_core/output_parsers/pydantic.py:35


class PydanticOutputParser(JsonOutputParser, Generic[TBaseModel]):
    """Parse an output using a Pydantic model."""

    pydantic_object: Annotated[type[TBaseModel], SkipValidation()]
    """The Pydantic model to parse."""

    def _parse_obj(self, obj: Any) -> TBaseModel:
        try:
            if issubclass(self.pydantic_object, pydantic.BaseModel):
                return self.pydantic_object.model_validate(obj)
            if issubclass(self.pydantic_object, pydantic.v1.BaseModel):
                return self.pydantic_object.parse_obj(obj)
            msg = (  # type: ignore[unreachable]
                "Unsupported model version for PydanticOutputParser: "
                f"{self.pydantic_object.__class__}"
            )
            raise OutputParserException(msg)
        except (pydantic.ValidationError, pydantic.v1.ValidationError) as e:
            raise self._parser_exception(e, obj) from e

    def _parser_exception(
        self, e: Exception, json_object: Any
    ) -> OutputParserException:
        json_string = json.dumps(json_object, ensure_ascii=False)
        name = self.pydantic_object.__name__
        msg = f"Failed to parse {name} from completion {json_string}. Got: {e}"
        return OutputParserException(msg, llm_output=json_string)

    @overload
    def parse_result(
        self, result: list[Generation], *, partial: Literal[False] = False
    ) -> TBaseModel: ...

    @overload
    def parse_result(

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Pass a Pydantic BaseModel subclass (v1 or v2) to pydantic_object
  2. For dataclasses/TypedDict, convert them to BaseModel or use a JSON-schema-based parser instead
  3. Add a runtime assert issubclass(pydantic_object, BaseModel) at wiring time to fail fast

Example fix

# before
parser = PydanticOutputParser(pydantic_object=MyDataclass)

# after
from pydantic import BaseModel
class MySchema(BaseModel):
    name: str
parser = PydanticOutputParser(pydantic_object=MySchema)
Defensive patterns

Strategy: type-guard

Validate before calling

from pydantic import BaseModel, v1
assert isinstance(parser.pydantic_object, type) and (
    issubclass(parser.pydantic_object, BaseModel)
    or issubclass(parser.pydantic_object, v1.BaseModel)
)

Type guard

from pydantic import BaseModel, v1

def is_pydantic_model(cls: object) -> bool:
    return isinstance(cls, type) and (issubclass(cls, BaseModel) or issubclass(cls, v1.BaseModel))

Prevention

When it happens

Trigger: Constructing PydanticOutputParser(pydantic_object=SomeDataclassOrArbitraryClass) while bypassing static typing (dynamic imports, plugin-provided classes); mutating pydantic_object after init.

Common situations: Migrating schemas to dataclasses/TypedDict while keeping PydanticOutputParser; config-driven parser construction from strings that resolve to non-Pydantic classes.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/d82e844fb6b35ffb. Report an issue: GitHub.