{"record":{"id":"b859b04363571e12","repo":"docling-project/docling","slug":"input-file-does-not-look-like-an-iterate-pdf-pag","errorCode":null,"errorMessage":"{input_file} does not look like an iterate_pdf_pages.py summary report.","messagePattern":"(.+?) does not look like an iterate_pdf_pages\\.py summary report\\.","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"perfs/plot_memory_metrics.py","lineNumber":46,"sourceCode":"        help=\"Output plot path.\",\n    )\n    return parser.parse_args()\n\n\ndef _resolve_metrics_files(input_file: Path) -> list[tuple[str, Path]]:\n    if input_file.suffix.lower() == \".jsonl\":\n        return [(input_file.stem, input_file)]\n\n    try:\n        report = json.loads(input_file.read_text(encoding=\"utf-8\"))\n    except json.JSONDecodeError as exc:\n        raise SystemExit(\n            f\"{input_file} is not valid JSONL or a JSON summary report.\"\n        ) from exc\n\n    runs = report.get(\"runs\")\n    if not isinstance(runs, list):\n        raise SystemExit(\n            f\"{input_file} does not look like an iterate_pdf_pages.py summary report.\"\n        )\n\n    metrics_files: list[tuple[str, Path]] = []\n    for index, run in enumerate(runs, start=1):\n        if not isinstance(run, dict):\n            continue\n        metrics_file = run.get(\"metrics_file\")\n        if not isinstance(metrics_file, str):\n            continue\n        thread_count = run.get(\"threads\")\n        label = (\n            f\"threads={thread_count}\"\n            if isinstance(thread_count, int)\n            else f\"run {index}\"\n        )\n        metrics_path = Path(metrics_file)\n        if not metrics_path.is_absolute():","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/perfs/plot_memory_metrics.py#L28-L64","documentation":"SystemExit raised by _resolve_metrics_files() in perfs/plot_memory_metrics.py when the input parses as JSON but does not contain a top-level 'runs' key holding a list. The plotter expects the summary-report schema written by iterate_pdf_pages.py, whose 'runs' array carries per-run entries with 'metrics_file' paths; a JSON file without that structure is rejected.","triggerScenarios":"Passing a valid JSON file that is not an iterate_pdf_pages.py summary — e.g. a DoclingDocument export, an experiment config, or a report from an older/newer script version where the key is missing or renamed.","commonSituations":"Schema drift between script versions (older summaries without 'runs'); passing the per-run metrics JSON file itself (which has event objects, not a runs list) instead of the summary; hand-written JSON wrappers around benchmark output.","solutions":["Regenerate the summary with the same (current) version of iterate_pdf_pages.py, which writes the runs array, and pass that file to the plotter.","Confirm the top-level shape: 'python -c \"import json;d=json.load(open('r.json'));print(list(d))\"' should show 'runs'.","If you only have raw .jsonl metrics, pass the .jsonl file directly instead of wrapping it in JSON."],"exampleFix":"# before\n$ python perfs/plot_memory_metrics.py per_run_metrics.json  # a metrics event file\n# SystemExit: ... does not look like an iterate_pdf_pages.py summary report.\n\n# after\n$ python perfs/iterate_pdf_pages.py --report-file summary.json ...\n$ python perfs/plot_memory_metrics.py summary.json","handlingStrategy":"validation","validationCode":"import json\n\ndef is_summary_report(path: str) -> bool:\n    try:\n        data = json.loads(Path(path).read_text(encoding=\"utf-8\"))\n    except json.JSONDecodeError:\n        return False\n    return isinstance(data, dict) and isinstance(data.get(\"runs\"), list)","typeGuard":"def is_iterate_summary(data: object) -> bool:\n    return isinstance(data, dict) and isinstance(data.get(\"runs\"), list)","tryCatchPattern":null,"preventionTips":["Always generate summaries and plots with the same repo version so the schema matches.","Pass raw .jsonl metrics directly instead of wrapping them in custom JSON.","Add a schema smoke check to benchmark pipelines after writing the report."],"tags":["perf-tooling","json","schema","cli"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}