Skip to content

[repo-health] Medium: parse_llm_json brace scanner is not string-aware — a "}" inside a JSON string silently discards all structured findings #136

Description

@Liohtml

Summary

parse_llm_json() extracts the first JSON object via naive brace-depth counting. Any } or { inside a string value — entirely plausible in an LLM's free-text findings or overall_impression — corrupts the depth counter, so the scanner cuts the object short and json.loads fails. parse_llm_response then swallows the error and returns the raw text as overall_impression, meaning all structured findings are silently lost for that analysis.

Category

Correctness

Severity

Medium — silent degradation of the primary LLM output path, input-dependent and hard to reproduce.

Location

  • File: src/medcheck/llm/base.py lines 110–123

Details

def parse_llm_json(raw: str) -> dict[str, Any]:
    start = raw.index("{")
    depth = 0
    for i, ch in enumerate(raw[start:], start):
        if ch == "{":
            depth += 1
        elif ch == "}":
            depth -= 1
        if depth == 0:
            result: dict[str, Any] = json.loads(raw[start : i + 1])
            return result

Example failing input: {"overall_impression": "Normal study (see notes: {contrast} was not administered)", ...} — the } after contrast terminates the scan mid-string.

Suggested Fix

Replace the manual scan with Python's incremental decoder, which is string/escape-aware:

def parse_llm_json(raw: str) -> dict[str, Any]:
    start = raw.index("{")
    result, _ = json.JSONDecoder().raw_decode(raw[start:])
    if not isinstance(result, dict):
        raise ValueError("No valid JSON object found")
    return result

Add a test with braces inside string values.

Effort Estimate

30 min


Automated finding from repo health check (2026-07-10)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions