{"record":{"id":"c92369de092da9b5","repo":"deepset-ai/haystack","slug":"context-window-must-be-a-positive-number-of-toke","errorCode":null,"errorMessage":"`context_window` must be a positive number of tokens, got {context_window}.","messagePattern":"`context_window` must be a positive number of tokens, got (.+?)\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"haystack/hooks/compaction/hooks.py","lineNumber":92,"sourceCode":"        token_counter: TokenCounter | None = None,\n    ) -> None:\n        \"\"\"\n        Initialize the hook with a compactor and the window it has to fit in.\n\n        :param compactor: The `Compactor` that rewrites the conversation.\n        :param context_window: The model's context window in tokens. Everything else is a fraction of this, so moving to\n            a different model means changing only this number.\n        :param compact_at: The fraction of the window at which compaction starts. Leave room above it for the reply and\n            the tool results it triggers, which land on top of what was measured.\n        :param compact_to: The fraction of the window compaction aims to bring the conversation down to. Lower means\n            compacting less often but losing more each time.\n        :param token_counter: The `TokenCounter` used to size the messages the chat generator has not reported on yet.\n            Defaults to `ApproximateTokenCounter`, which needs no extra dependency.\n        :raises ValueError: If `context_window` is not positive, or the fractions are not\n            `0 < compact_to < compact_at <= 1`.\n        \"\"\"\n        if context_window < 1:\n            raise ValueError(f\"`context_window` must be a positive number of tokens, got {context_window}.\")\n        if not 0 < compact_to < compact_at <= 1:\n            raise ValueError(\n                f\"`compact_at` and `compact_to` must satisfy 0 < compact_to < compact_at <= 1, got \"\n                f\"compact_at={compact_at} and compact_to={compact_to}. A target at or above the trigger would leave \"\n                f\"the conversation over the trigger after compacting, so it would be attempted again every step.\"\n            )\n        self.compactor = compactor\n        self.context_window = context_window\n        self.compact_at = compact_at\n        self.compact_to = compact_to\n        self.token_counter = token_counter or ApproximateTokenCounter()\n\n    def run(self, state: State) -> None:\n        \"\"\"\n        Compact `state.data[\"messages\"]` if the conversation fills too much of the window.\n\n        :param state: The Agent's live `State`. Read to decide whether to compact, and rewritten in place when the\n            compactor returns a compacted conversation.","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/hooks/compaction/hooks.py#L74-L110","documentation":"This ValueError comes from a compaction hook's __init__ (haystack/hooks/compaction/hooks.py:92). The hook needs to know the model's context window size to decide when to compact; it refuses to run with a nonsensical size. A context_window of 0 or negative would make trigger/threshold math meaningless.","triggerScenarios":"Passing context_window=0, a negative number, or an unset/None-ish value coerced to 0 when constructing the compaction hook class.","commonSituations":"Hardcoding a placeholder of 0 intending to fill it later; reading the context window from an empty config/env var and getting 0; copy-pasting a template constructor call without setting the value.","solutions":["Set context_window to the model's actual context size in tokens, e.g. context_window=128000.","If it comes from config, assert it is a positive int before constructing: value = int(cfg); assert value > 0.","Look up the correct value in the model provider's docs if unsure."],"exampleFix":"// before\nhook = CompactionHook(context_window=0)\n// after\nhook = CompactionHook(context_window=128_000)","handlingStrategy":"validation","validationCode":"def validate_context_window(context_window):\n    if not isinstance(context_window, int) or context_window < 1:\n        raise ValueError(f\"context_window must be a positive int, got {context_window!r}\")\n# call before constructing the hook","typeGuard":"def is_positive_int(v) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool) and v > 0","tryCatchPattern":"try:\n    hook = CompactionHook(context_window=cw)\nexcept ValueError as e:\n    logger.error(\"bad context_window: %s\", e)\n    hook = CompactionHook(context_window=128_000)","preventionTips":["Store the model's context window in a central config/constants module","Validate config values at load time, before building pipelines","Never hardcode 0 as a placeholder","Log the resolved context_window at startup"],"tags":["validation","constructor","config","compaction"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}