langchain-ai/langchain · error · ValueError

If env_var is set, handle_class must also be set to a non-No

Error message

If env_var is set, handle_class must also be set to a non-None value.

What it means

configure (from langchain_core.tracers.context) registers callback hooks tied to a context var. Because an env_var-based hook needs a handler class to instantiate when the env var is set, passing env_var without handle_class is rejected with ValueError.

Source

Thrown at libs/core/langchain_core/tracers/context.py:191

    inheritable: bool,  # noqa: FBT001
    handle_class: type[BaseCallbackHandler] | None = None,
    env_var: str | None = None,
) -> None:
    """Register a configure hook.

    Args:
        context_var: The context variable.
        inheritable: Whether the context variable is inheritable.
        handle_class: The callback handler class.
        env_var: The environment variable.

    Raises:
        ValueError: If `env_var` is set, `handle_class` must also be set to a non-`None`
            value.
    """
    if env_var is not None and handle_class is None:
        msg = "If env_var is set, handle_class must also be set to a non-None value."
        raise ValueError(msg)

    _configure_hooks.append(
        (
            # the typings of ContextVar do not have the generic arg set as covariant
            # so we have to cast it
            cast("ContextVar[BaseCallbackHandler | None]", context_var),
            inheritable,
            handle_class,
            env_var,
        )
    )


register_configure_hook(run_collector_var, inheritable=False)

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Pass handle_class together with env_var: configure(var, env_var='X', handle_class=MyHandler)
  2. If no class-based handler is intended, drop env_var
  3. Ensure handle_class is imported before the configure call (a failed import yielding None triggers this)

Example fix

# before
configure(
    context_var=my_var,
    inheritable=False,
    env_var="ENABLE_MY_TRACER",
)

# after
from my_pkg.tracers import MyHandler

configure(
    context_var=my_var,
    inheritable=False,
    env_var="ENABLE_MY_TRACER",
    handle_class=MyHandler,
)
Defensive patterns

Strategy: validation

Validate before calling

def safe_configure(context_var, *, env_var=None, handle_class=None, **kw):
    if env_var is not None and handle_class is None:
        msg = f"env_var={env_var!r} requires handle_class"
        raise ValueError(msg)
    return configure(context_var, env_var=env_var, handle_class=handle_class, **kw)

Type guard

def is_handler_class(cls: object) -> bool:
    return isinstance(cls, type)

Try / catch

try:
    configure(context_var=var, env_var="MY_TRACER", handle_class=handler)
except ValueError as e:
    if "handle_class" in str(e):
        from langchain_core.tracers import LangChainTracer
        configure(context_var=var, env_var="MY_TRACER", handle_class=LangChainTracer)
    else:
        raise

Prevention

When it happens

Trigger: configure(context_var=my_var, env_var='MY_TRACER') with handle_class omitted or None.

Common situations: Custom tracing integrations copied from LangSmith's configure(...) call with the handler class accidentally removed; library code registering env-var-driven hooks dynamically.

Related errors


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