JuliusBrussee/caveman · error · ImportError
Install caveman-middleware[pydantic-ai] to use the Pydantic…
Error message
Install caveman-middleware[pydantic-ai] to use the Pydantic AI adapter
What it means
The Pydantic AI adapter is an optional extra of caveman-middleware. At import time the module tries to import pydantic_ai; if the package is absent it converts the ModuleNotFoundError into an actionable ImportError telling you which extra to install.
Solutions
- Run `pip install 'caveman-middleware[pydantic-ai]'`
- If you do not use Pydantic AI, remove the import of caveman_middleware.pydantic_ai from your code path
- Pin the extra in requirements/pyproject so deployment environments include it
Example fix
// before pip install caveman-middleware // after pip install 'caveman-middleware[pydantic-ai]'
Defensive patterns
Strategy: try-catch
Validate before calling
import importlib.util
if importlib.util.find_spec("pydantic_ai") is None:
raise SystemExit("Install caveman-middleware[pydantic-ai]") Try / catch
try:
from caveman_middleware import pydantic_ai
except ImportError as e:
if "pydantic-ai" in str(e):
logging.error("Run: pip install 'caveman-middleware[pydantic-ai]'")
raise Prevention
- Install with extras: pip install 'caveman-middleware[pydantic-ai]'
- Declare the extra in pyproject/requirements for all environments
- Keep dev and production dependency files in sync
- Smoke-test imports in CI before deployment
When it happens
Trigger: importing caveman_middleware.pydantic_ai (or anything that imports it) in an environment where the pydantic_ai distribution is not installed, e.g. after `pip install caveman-middleware` without extras.
Common situations: Fresh CI or container images built without optional extras; deploying to a slim runtime image that omits dev dependencies; a dependency bump that dropped the [pydantic-ai] extra.
Understand the failure class
Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.
Related errors
- Install caveman-middleware[autogen] to use the AutoGen…
- Install caveman-middleware[litellm] to use the LiteLLM…
- Install caveman-middleware[llama-index] to use the…
- Install caveman-middleware[mcp] for the native MCP adapter
- Install caveman-middleware[strands] to use the Strands…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/e8d9dcbb619752b7.
Report an issue: GitHub.
Appendix: source
Thrown at packages/middleware/python/caveman_middleware/pydantic_ai.py:25
import uuid
from contextlib import asynccontextmanager
from dataclasses import replace
from importlib.metadata import version
from typing import Any
try:
from pydantic_ai import RunContext, Tool
from pydantic_ai.capabilities import AbstractCapability
from pydantic_ai.messages import (
ModelMessage, ModelMessagesTypeAdapter, ModelRequest, ModelResponse,
ToolCallPart, ToolReturnPart,
)
from pydantic_ai.models import Model, ModelRequestContext, ModelRequestParameters
from pydantic_ai.models.wrapper import WrapperModel
from pydantic_ai.toolsets import FunctionToolset
from pydantic_core import PydanticSerializationError
except ModuleNotFoundError as error:
raise ImportError("Install caveman-middleware[pydantic-ai] to use the Pydantic AI adapter") from error
from caveman_cloud.middleware import Adapter, Candidate, MiddlewareError, MiddlewareRuntime, Scope
from caveman_cloud.middleware.runtime import RECOVERY_DESCRIPTION, RECOVERY_SCHEMA
from ._native import Attempt, manifest, owner
from ._versions import supports_framework
ADAPTER = Adapter("pydantic-ai", "0.1.0", "2.42.0", "pydantic-ai-message-v1")
def scope_from_run(ctx: RunContext, *, namespace: str) -> Scope:
"""Use native conversation identity plus application-owned branch metadata."""
if not isinstance(ctx.conversation_id, str) or not ctx.conversation_id:
raise ValueError("Pydantic AI middleware requires a native conversation_id")
metadata = ctx.metadata or {}
return Scope(namespace, ctx.conversation_id, metadata.get("caveman_branch_id", "main"),
metadata.get("caveman_cache_epoch", "0"))
View on GitHub (pinned to 3ee70a1026)