dgtlmoon/changedetection.io · warning · LLMInputTooLargeError
Change too large for AI summary ({len(text):,} chars, limit
Error message
Change too large for AI summary ({len(text):,} chars, limit {max_chars:,}) What it means
A guard in the LLM evaluator that raises LLMInputTooLargeError before any model call when the text to summarise exceeds max_chars. This is a deliberate pre-flight check so huge diffs never reach (and cost) the LLM API.
Source
Thrown at changedetectionio/llm/evaluator.py:83
Always returns at least 1 — unlimited is not permitted.
"""
env_val = os.getenv('LLM_MAX_INPUT_CHARS', '').strip()
if env_val.isdigit() and int(env_val) > 0:
return int(env_val)
stored = get_llm_settings(datastore).max_input_chars
if stored and stored > 0:
return stored
return _DEFAULT_MAX_INPUT_CHARS
class LLMInputTooLargeError(Exception):
pass
def _check_input_size(text: str, max_chars: int) -> None:
"""Raise LLMInputTooLargeError if text exceeds max_chars."""
if len(text) > max_chars:
raise LLMInputTooLargeError(
f"Change too large for AI summary ({len(text):,} chars, limit {max_chars:,})"
)
def _thinking_extra_body(model: str, budget: int) -> dict | None:
"""Return litellm extra_body to control thinking for models that support it.
The `thinkingConfig.thinkingBudget` payload is Gemini-specific (Anthropic and
OpenAI reasoning models use different parameters), so we gate on the gemini/
provider prefix first, then defer to litellm's model registry for the actual
"does this model think?" decision. That picks up new Gemini variants and
rolling aliases (`gemini-flash-latest`, etc.) as litellm's registry tracks
them, without us hardcoding model names here.
"""
if not model.startswith('gemini/'):
return None
try:
import litellmView on GitHub (pinned to 5d9c7c6da7)
Solutions
- Increase max_chars in the LLM/summary settings if your model context allows it
- Limit what is sent: use CSS/xpath filters or ignore-text rules on the watch so the diff shrinks
- Catch LLMInputTooLargeError and skip AI summarisation for oversized changes
Example fix
# before
summary = summarise_change(diff, max_chars=50000)
# after
try:
summary = summarise_change(diff, max_chars=50000)
except LLMInputTooLargeError:
summary = None # change too big to summarise Defensive patterns
Strategy: type-guard
Validate before calling
if len(diff_text) > max_chars:
diff_text = None # skip AI summary for oversized change Type guard
def summarisable(text: str, max_chars: int) -> bool:
return len(text) <= max_chars Try / catch
from changedetectionio.llm.evaluator import LLMInputTooLargeError
try:
summary = summarise_change(diff, max_chars=mc)
except LLMInputTooLargeError:
summary = None Prevention
- Pre-check len(text) against the configured max_chars
- Use watch filters (CSS/xpath/ignore) to keep diffs small
- Treat AI summary as optional enrichment, never a required step
When it happens
Trigger: Calling summarise_change, preview_extract, or evaluate_change with a change/diff whose character count exceeds the configured max_chars limit (set by the LLM config, e.g. notification/summariser settings). Large page snapshots or full-page diffs easily exceed it.
Common situations: Watching pages with very large content (logs, feeds, minified JS diffs); enabling AI summaries on watches whose snapshots are megabytes; lowering the char limit in config while existing watches have big diffs.
Related errors
- XPath not permitted in this field!
- abort(400) # Bad Request if the filename doesn't match the
- abort(404)
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/3281ba67d694ef11.
Report an issue: GitHub.