langchain-ai/langchain · error · ValueError

maxsize must be greater than 0

Error message

maxsize must be greater than 0

What it means

`BaseCache` subclass `InMemoryCache.__init__` (libs/core/langchain_core/caches.py) validates its `maxsize` argument: passing a non-None value <= 0 raises `ValueError('maxsize must be greater than 0')`. It is a fail-fast constructor check so the eviction logic never sees an invalid bound.

Source

Thrown at libs/core/langchain_core/caches.py:198

    """

    def __init__(self, *, maxsize: int | None = None) -> None:
        """Initialize with empty cache.

        Args:
            maxsize: The maximum number of items to store in the cache.

                If `None`, the cache has no maximum size.

                If the cache exceeds the maximum size, the oldest items are removed.

        Raises:
            ValueError: If `maxsize` is less than or equal to `0`.
        """
        self._cache: dict[tuple[str, str], RETURN_VAL_TYPE] = {}
        if maxsize is not None and maxsize <= 0:
            msg = "maxsize must be greater than 0"
            raise ValueError(msg)
        self._maxsize = maxsize

    def lookup(self, prompt: str, llm_string: str) -> RETURN_VAL_TYPE | None:
        """Look up based on `prompt` and `llm_string`.

        Args:
            prompt: A string representation of the prompt.

                In the case of a chat model, the prompt is a non-trivial
                serialization of the prompt into the language model.
            llm_string: A string representation of the LLM configuration.

        Returns:
            On a cache miss, return `None`. On a cache hit, return the cached value.
        """
        return self._cache.get((prompt, llm_string), None)

    def update(self, prompt: str, llm_string: str, return_val: RETURN_VAL_TYPE) -> None:

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Pass a positive integer: `InMemoryCache(maxsize=1000)`
  2. Pass `maxsize=None` for an unbounded cache instead of 0 or -1
  3. If maxsize comes from config, normalize before constructing: `maxsize = int(v) if v and int(v) > 0 else None`
  4. Add a unit test asserting the constructor raises for 0 and negative values

Example fix

# before
cache = InMemoryCache(maxsize=int(os.environ.get("CACHE_MAXSIZE", "0")))

# after
raw = os.environ.get("CACHE_MAXSIZE")
cache = InMemoryCache(maxsize=int(raw) if raw and int(raw) > 0 else None)
Defensive patterns

Strategy: validation

Validate before calling

def to_maxsize(raw: str | int | None) -> int | None:
    if raw in (None, ''):
        return None
    n = int(raw)
    return n if n > 0 else None  # or raise on invalid config

cache = InMemoryCache(maxsize=to_maxsize(os.environ.get('CACHE_MAXSIZE')))

Prevention

When it happens

Trigger: Instantiating `InMemoryCache(maxsize=0)` or a negative maxsize; computing maxsize from config/env (e.g. `maxsize=int(os.environ.get('CACHE_MAX', 0))`) where the default or parse yields 0; passing `-1` intending 'unlimited'

Common situations: Env-var driven configuration defaulting to 0 when unset; porting code from LRU implementations where -1 means unbounded; YAML/TOML config typos.

Related errors


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