langchain-ai/langchain · error · NotImplementedError
Remapping for fields starting with '_' or fields with a name
Error message
Remapping for fields starting with '_' or fields with a name matching a reserved name {_RESERVED_NAMES} is not supported if the field is a pydantic Field instance. Got {key}. What it means
Raised by `_remap_field_definitions` in `langchain_core.utils.pydantic` (used by `create_model`-style dynamic model creation) when a field name starts with `_` or collides with a pydantic-reserved name (`model_`-prefixed / internal names in `_RESERVED_NAMES`) AND the field value is a pydantic `FieldInfo` (i.e. `Field(...)`). Remapping such names relies on re-wrapping a `(type, default)` tuple; it cannot preserve a full `FieldInfo`, so it refuses with `NotImplementedError` instead of silently dropping constraints.
Source
Thrown at libs/core/langchain_core/utils/pydantic.py:540
# "model_fields_set", "model_json_schema", "model_parametrized_name",
# "model_post_init", "model_rebuild", "model_validate", "model_validate_json",
# "model_validate_strings"
_RESERVED_NAMES = {key for key in dir(BaseModel) if not key.startswith("_")}
def _remap_field_definitions(field_definitions: dict[str, Any]) -> dict[str, Any]:
"""This remaps fields to avoid colliding with internal pydantic fields."""
remapped = {}
for key, value in field_definitions.items():
if key.startswith("_") or key in _RESERVED_NAMES:
# Let's add a prefix to avoid colliding with internal pydantic fields
if isinstance(value, FieldInfoV2):
msg = (
f"Remapping for fields starting with '_' or fields with a name "
f"matching a reserved name {_RESERVED_NAMES} is not supported if "
f" the field is a pydantic Field instance. Got {key}."
)
raise NotImplementedError(msg)
type_, default_ = value
remapped[f"private_{key}"] = (
type_,
Field(
default=default_,
alias=key,
serialization_alias=key,
title=key.lstrip("_").replace("_", " ").title(),
),
)
else:
remapped[key] = value
return remapped
def create_model_v2(
model_name: str,
*,View on GitHub (pinned to e32fa9a52e)
Solutions
- Rename the field so it does not start with `_` and is not in `_RESERVED_NAMES` (preferred — remapping then works and keeps an alias).
- If renaming is impossible, define the field as a plain tuple `(type, default)` instead of `Field(...)`; the helper can then remap it with an alias preserving the original name.
- Pre-normalize external field names (strip leading underscores, prefix reserved names) before generating the model.
Example fix
# before
create_model("M", **{"_count": (int, Field(default=0, ge=0))}) # NotImplementedError
# after
create_model("M", **{"_count": (int, 0)}) # tuple form: remapped with alias '_count'
# or better: rename
create_model("M", count=(int, Field(default=0, ge=0))) Defensive patterns
Strategy: validation
Validate before calling
from langchain_core.utils.pydantic import _RESERVED_NAMES
from pydantic.fields import FieldInfo
def check_field_defs(field_definitions: dict) -> None:
for name, value in field_definitions.items():
if (name.startswith("_") or name in _RESERVED_NAMES) and isinstance(value, FieldInfo):
raise ValueError(
f"field {name!r}: reserved/underscore names must use (type, default) tuples, not Field(...)"
) Try / catch
try:
create_model("M", **field_definitions)
except NotImplementedError as e:
# rewrite offending FieldInfo as (type, default) and retry
... Prevention
- Sanitize external field names (strip leading '_', rename model_* keys) before create_model.
- Reserve Field(...) for non-underscore, non-reserved names only.
- Add a unit test for dynamic model generation from your spec source.
When it happens
Trigger: Building a dynamic model (e.g. via `langchain_core.utils.pydantic.create_model` / tool-args model creation) with field definitions like `{"_private": (str, Field(...))}` or `{"model_config_override": Field(default=1, ...)}` — any reserved/underscore name mapped to a `Field(...)` instance rather than a `(type, default)` tuple.
Common situations: Structured-output schemas generated from external specs (OpenAPI, JSON Schema, database columns) that contain leading-underscore or `model_*` column names; converting user-supplied dicts into tool argument models where keys are arbitrary; naming a field `model_fields`, `model_config`, etc.
Related errors
- When specifying __root__ no other fields should be provided.
- Either data or path must be provided
- ToolMessage content should be a string or a list of string/d
- If multiple pydantic schemas are provided then args_only sho
- Dict Pydantic schema unsupported with args_only: {self.pydan
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/567d78de5f9bbb6e.
Report an issue: GitHub.