srbhr/Resume-Matcher · error · ValueError
Content too large for JSON extraction: {len(content)} bytes
Error message
Content too large for JSON extraction: {len(content)} bytes What it means
_extract_json enforces MAX_JSON_CONTENT_SIZE as a JSON-010 safety limit; if the LLM response text exceeds it (len(content) > limit), it refuses to parse and raises this ValueError to bound memory/CPU on huge responses.
Source
Thrown at apps/backend/app/llm.py:1111
stripped = re.sub(r"<think>.*?</think>", "", content, flags=re.DOTALL)
# Also handle unclosed <think> tag (model may still be "thinking" at end)
stripped = re.sub(r"<think>.*", "", stripped, flags=re.DOTALL)
return stripped.strip()
def _extract_json(content: str, _depth: int = 0) -> str:
"""Extract JSON from LLM response, handling various formats.
LLM-001: Improved to detect and reject likely truncated JSON.
LLM-007: Improved error messages for debugging.
JSON-010: Added recursion depth and size limits.
"""
# JSON-010: Safety limits
if _depth > MAX_JSON_EXTRACTION_RECURSION:
raise ValueError(
f"JSON extraction exceeded max recursion depth: {_depth}")
if len(content) > MAX_JSON_CONTENT_SIZE:
raise ValueError(
f"Content too large for JSON extraction: {len(content)} bytes")
original = content
# Strip thinking model tags (deepseek-r1, qwq, etc.)
if "<think>" in content:
content = _strip_thinking_tags(content)
# Remove markdown code blocks
if "```json" in content:
content = content.split("```json")[1].split("```")[0]
elif "```" in content:
parts = content.split("```")
if len(parts) >= 2:
content = parts[1]
# Remove language identifier if present (e.g., "json\n{...")
if content.startswith(("json", "JSON")):
content = content[4:]View on GitHub (pinned to 116f9cc3b0)
Solutions
- Cap output size via max_tokens on the completion request
- Prompt the model to produce concise JSON and split very large inputs into smaller requests
- Truncate/chunk the resume or job text passed to analyze/generate prompts
- If justified, raise MAX_JSON_CONTENT_SIZE in llm.py
Example fix
// before
const response = await router.acompletion({ ...kwargs });
// after
const response = await router.acompletion({ ...kwargs, max_tokens: 4096 }); Defensive patterns
Strategy: validation
Validate before calling
MAX_JSON_CONTENT_SIZE = 1_000_000 # match llm.py
def content_size_ok(s: str) -> bool:
return len(s.encode('utf-8')) <= MAX_JSON_CONTENT_SIZE
# check the raw response before parsing
assert content_size_ok(response_text), "LLM response exceeds JSON extraction size limit" Try / catch
try:
data = await complete_json(prompt)
except ValueError as e:
if "Content too large" in str(e):
data = await complete_json(prompt + " Be concise; limit output to essential fields.")
else:
raise Prevention
- Always set max_tokens on LLM calls to bound response size
- Chunk large resumes/job descriptions into smaller analysis requests
- Instruct models to emit concise JSON
- Monitor response sizes in logs to tune MAX_JSON_CONTENT_SIZE
When it happens
Trigger: complete_json gets a response whose content length exceeds MAX_JSON_CONTENT_SIZE bytes — e.g. the model echoed the whole resume plus verbose enhancements, or generated runaway repetitive output.
Common situations: Very large resumes/jobs fed into analysis prompts with no output size guidance; model loops and produces megabytes of text; missing max_tokens cap on the completion call.
Related errors
- JSON extraction exceeded max recursion depth: {_depth}
- No JSON found in response: {original[:200]}
- LLM completion failed. Please check your API configuration a
- Empty response from LLM
- Failed to parse JSON after {retries + 1} attempts: {e}
AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28).
Data as JSON: /api/errors/9775738e58ea746c.
Report an issue: GitHub.