deepset-ai/haystack · error
`min_tokens` must be at least 0, got {min_tokens}.
Error message
`min_tokens` must be at least 0, got {min_tokens}. What it means
ToolResultPruningHook requires min_tokens >= 0 in __init__ (haystack/hooks/compaction/tool_result_pruning.py:75). min_tokens is the size threshold below which tool results are left untouched; negative values are invalid.
Source
Thrown at haystack/hooks/compaction/tool_result_pruning.py:75
:param min_keep_steps: The minimum number of recent tool-calling Agent steps whose results remain untouched,
even when they exceed the target. Must be at least 1, which ensures the current result batch remains intact
until the model has acted on it.
:param min_tokens: Only prune tool-result messages that use more than this many tokens. Small results cost
little and are often the ones worth keeping.
:param placeholder: The text left in place of a pruned result, replacing the built-in one. May contain
`{tool_name}`, which is filled in with the name of the tool that produced the result.
:param skip_meta_keys: Results whose `meta` contains any of these keys are left alone. The default covers
results that a `ToolResultOffloadHook` already replaced with a reference to stored content: pruning one of
those would destroy the reference the model needs to read it back.
:raises ValueError: If `min_keep_steps` is less than 1 or `min_tokens` is negative.
"""
if min_keep_steps < 1:
raise ValueError(
f"`min_keep_steps` must be at least 1, got {min_keep_steps}. The most recent tool-calling step "
f"contains results the model may still need."
)
if min_tokens < 0:
raise ValueError(f"`min_tokens` must be at least 0, got {min_tokens}.")
self.min_keep_steps = min_keep_steps
self.min_tokens = min_tokens
self.placeholder = placeholder
# Normalized to a tuple so a round trip through `to_dict`, which has to emit a list, restores the same type.
self.skip_meta_keys = tuple(skip_meta_keys)
def compact(
self, messages: list[ChatMessage], target_tokens: int, token_counter: TokenCounter
) -> list[ChatMessage] | None:
"""
Replace the content of prunable tool results with a placeholder.
Results are considered oldest first and pruning stops as soon as the conversation reaches `target_tokens`.
This keeps as much original output as possible. Results from the most recent `min_keep_steps` tool-calling
Agent steps are never considered, even when the target cannot otherwise be reached. After measuring the initial
conversation, the running total is updated with per-result token deltas to avoid repeatedly counting the full
context.
View on GitHub (pinned to e318778c9b)
Solutions
- Pass min_tokens >= 0 (use 0 to prune any size).
- Clamp: min_tokens = max(0, value).
- Correct the config/env value feeding the constructor.
Example fix
// before hook = ToolResultPruningHook(min_tokens=-100) // after hook = ToolResultPruningHook(min_tokens=max(0, configured_min_tokens))
Defensive patterns
Strategy: validation
Validate before calling
def validate_min_tokens(v):
if not isinstance(v, int) or v < 0:
raise ValueError(f"min_tokens must be >= 0, got {v!r}")
validate_min_tokens(cfg.get("min_tokens", 50)) Type guard
def is_non_negative_int(v) -> bool:
return isinstance(v, int) and not isinstance(v, bool) and v >= 0 Try / catch
try:
hook = ToolResultPruningHook(min_tokens=t)
except ValueError as e:
logger.error("bad min_tokens: %s", e)
hook = ToolResultPruningHook(min_tokens=0) Prevention
- Use 0 (not negative) to mean 'prune regardless of size'
- Clamp deltas with max(0, value)
- Validate config at load time
When it happens
Trigger: Constructing the hook with min_tokens < 0, typically from a subtraction-based computation or a bad config value.
Common situations: Computing min_tokens as a delta that goes negative; typos in config; conflating '0 means prune everything small' with negative 'disable' values.
Related errors
- `min_keep_steps` must be at least 1, got {min_keep_steps}. T
- `context_window` must be a positive number of tokens, got {c
- `compact_at` and `compact_to` must satisfy 0 < compact_to <
- `min_keep_steps` must be at least 0, got {min_keep_steps}.
- `min_keep_steps` must be at least 0, got {min_keep_steps}.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/fa5919abae7c301c.
Report an issue: GitHub.