srbhr/Resume-Matcher · error · ValueError

No JSON found in response: {original[:200]}

Error message

No JSON found in response: {original[:200]}

What it means

After stripping think tags, extracting code fences, and locating JSON boundaries, _extract_json raises this ValueError when no JSON structure can be found at all in the model response. It also logs a 200-char preview of the unrecognized format (LLM-007) for debugging.

Source

Thrown at apps/backend/app/llm.py:1181

                "JSON extraction found unbalanced braces (depth=%d), possible truncation",
                depth,
            )

        if end_idx != -1:
            return content[: end_idx + 1]

    # Try to find JSON object in the content (only if not already at start)
    start_idx = content.find("{")
    if start_idx > 0:
        # Only recurse if { is found after position 0 to avoid infinite recursion
        return _extract_json(content[start_idx:], _depth + 1)

    # LLM-007: Log unrecognized format for debugging
    logging.error(
        "Could not extract JSON from response format. Content preview: %s",
        content[:200] if content else "<empty>",
    )
    raise ValueError(f"No JSON found in response: {original[:200]}")


async def complete_json(
    prompt: str,
    system_prompt: str | None = None,
    config: LLMConfig | None = None,
    max_tokens: int = 4096,
    retries: int = 2,
    schema_type: str = "resume",
) -> dict[str, Any]:
    """Make a completion request expecting JSON response.

    Uses JSON mode when available, with app-level retries for content-quality
    issues (malformed JSON, truncation).  Transport retries (429, 500, timeout)
    are handled by the Router and are NOT retried again here.

    Args:
        schema_type: Expected schema — "resume", "enrichment", "diff",

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Strengthen the prompt: 'Respond with ONLY a valid JSON object. Start with { and end with }.'
  2. Use a model/provider that supports JSON mode (see _supports_json_mode) so response_format json_object is enforced
  3. Check the logged 'Could not extract JSON from response format. Content preview:' line to see what the model actually returned
  4. Retry with a stronger model or lower temperature; complete_json already retries with a corrective suffix

Example fix

// before
const prompt = 'List the skills in this resume.';
// after
const prompt = 'List the skills in this resume. Respond with ONLY a JSON object like {"skills": [...]}. No prose.';
Defensive patterns

Strategy: retry

Validate before calling

import json, re
def looks_like_json(s: str) -> bool:
    s = s.strip()
    if s.startswith("```"): 
        s = re.sub(r"^```[a-z]*\n|```$", "", s).strip()
    return s.startswith(("{", "[")) and bool(_try_loads(s))

def _try_loads(s):
    try: json.loads(s)
    except Exception: return None
    return True

Try / catch

try:
    data = await complete_json(prompt)
except ValueError as e:
    if e.message.starts with "No JSON found":
        # inspect logged content preview, then retry with stricter instruction
        data = await complete_json(prompt + "\nOutput ONLY raw JSON. No markdown, no explanation.")
    else:
        raise

Prevention

When it happens

Trigger: complete_json receives a response containing no parseable JSON object/array — the model answered in plain prose, refused the task, or wrapped output in an unrecognized format the extractor doesn't handle.

Common situations: Weak/small model ignoring 'output JSON only' instructions; model safety-refuses the prompt; prompt ambiguous so the model narrates instead of emitting JSON; non-JSON-mode model where response_format is unsupported.

Related errors


AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28). Data as JSON: /api/errors/24762dee554e9925. Report an issue: GitHub.