{"record":{"id":"35f96e85541e2dca","repo":"headroomlabs-ai/headroom","slug":"max-size-must-be-at-least-1-got-max-size","errorCode":null,"errorMessage":"max_size must be at least 1, got {max_size}","messagePattern":"max_size must be at least 1, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/memory/adapters/cache.py","lineNumber":54,"sourceCode":"\n    The cache uses an OrderedDict internally where:\n    - Most recently used items are at the end\n    - Least recently used items are at the beginning\n    - On capacity overflow, the first (oldest) item is evicted\n    \"\"\"\n\n    def __init__(self, max_size: int = 1000) -> None:\n        \"\"\"Initialize the LRU cache.\n\n        Args:\n            max_size: Maximum number of entries to store. When exceeded,\n                      the least recently used entry is evicted.\n\n        Raises:\n            ValueError: If max_size is less than 1.\n        \"\"\"\n        if max_size < 1:\n            raise ValueError(f\"max_size must be at least 1, got {max_size}\")\n\n        self._max_size = max_size\n        self._cache: OrderedDict[str, Memory] = OrderedDict()\n        self._lock = Lock()\n\n    async def get(self, memory_id: str) -> Memory | None:\n        \"\"\"Get a memory from the cache.\n\n        Moves the accessed item to the end (most recently used position).\n\n        Args:\n            memory_id: The memory ID to retrieve.\n\n        Returns:\n            The Memory object if found, None otherwise.\n        \"\"\"\n        with self._lock:\n            if memory_id not in self._cache:","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/memory/adapters/cache.py#L36-L72","documentation":"LRUMemoryCache.__init__ validates its max_size argument and raises ValueError when it is less than 1, because an empty cache can never store anything and negative sizes are meaningless. It is a fail-fast config check before any OrderedDict/lock state is created.","triggerScenarios":"Constructing LRUMemoryCache(max_size=0) or a negative value — typically from a config file field, an environment-derived value that defaulted to 0, or arithmetic like max_size=len(items)-10 evaluating to <= 0.","commonSituations":"YAML/TOML config with cache_size: 0 to 'disable' the cache (use None/bypass instead); env var parsed to 0 when unset; test fixtures shrinking cache size below 1; derived sizes (total_budget - overhead) going negative.","solutions":["Pass max_size >= 1: LRUMemoryCache(max_size=1) is the smallest valid cache.","If the intent was 'no caching', skip constructing the cache rather than passing 0.","Guard derived values: max(max_size, 1) at the call site when the number is computed.","Validate config values at load time with a clear message before they reach the constructor."],"exampleFix":"# before\ncache = LRUMemoryCache(max_size=0)  # ValueError\n\n# after\ncache = LRUMemoryCache(max_size=1)  # smallest valid; or don't cache at all","handlingStrategy":"validation","validationCode":"def resolve_cache_size(raw: int | str | None, default: int = 1000) -> int:\n    n = int(raw) if raw is not None else default\n    if n < 1:\n        raise ValueError(f\"cache size must be >= 1, got {n}; unset means 'no cache', 0 is invalid\")\n    return n","typeGuard":"def is_valid_cache_size(n: object) -> bool:\n    \"\"\"LRUMemoryCache accepts max_size only when it's an int >= 1.\"\"\"\n    return isinstance(n, int) and not isinstance(n, bool) and n >= 1","tryCatchPattern":"try:\n    cache = LRUMemoryCache(max_size=cfg[\"cache_size\"])\nexcept ValueError as e:\n    raise SystemExit(f\"invalid cache config: {e}; set cache_size >= 1 or disable caching\") from None","preventionTips":["Validate numeric config once at load time, near the config source.","Never use 0 to express 'disabled' — model absence with Optional[LRUMemoryCache] = None.","Clamp computed sizes: max(1, computed) when the value is derived arithmetic."],"tags":["validation","configuration","cache","memory","valueerror"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}