{"record":{"id":"db6b8262e68b47c6","repo":"nexu-io/open-design","slug":"render-for-html-comparison-requires-at-least-one-r","errorCode":null,"errorMessage":"render_for_html_comparison requires at least one report","messagePattern":"render_for_html_comparison requires at least one report","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"design-templates/last30days/scripts/lib/render.py","lineNumber":218,"sourceCode":"    # the same warnings via collect_html_warnings() routed to stderr by the\n    # CLI, so they can fix quality issues before sharing.\n    _append_html_footer(lines, report, save_path)\n    return \"\\n\".join(lines).strip() + \"\\n\"\n\n\ndef render_for_html_comparison(\n    entity_reports: list[tuple[str, schema.Report]],\n    synthesis_md: str | None = None,\n    *,\n    save_path: str | None = None,\n) -> str:\n    \"\"\"Render comparison markdown intended for shareable HTML conversion.\n\n    Same semantics as render_for_html(), but metadata and data quality notes\n    are aggregated across the compared entities.\n    \"\"\"\n    if not entity_reports:\n        raise ValueError(\"render_for_html_comparison requires at least one report\")\n\n    entities = [label for label, _ in entity_reports]\n    main_report = entity_reports[0][1]\n    meta = (\n        f\"<!-- META: {main_report.range_from} to {main_report.range_to} \"\n        f\"· comparing {len(entities)}: {', '.join(entities)} -->\"\n    )\n    lines = [\n        *_render_badge(),\n        meta,\n    ]\n    if synthesis_md:\n        lines.extend([\"\", synthesis_md.strip()])\n    # Comparison data quality notes also go to stderr, not into the artifact.\n    _append_html_footer(lines, main_report, save_path)\n    return \"\\n\".join(lines).strip() + \"\\n\"\n\n","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/design-templates/last30days/scripts/lib/render.py#L200-L236","documentation":"render_for_html_comparison requires at least one (label, Report) pair because it builds comparison metadata and quality notes by reading entity_reports[0]. An empty list would IndexError at main_report access, so the function guards up front with ValueError.","triggerScenarios":"Calling render_for_html_comparison([]) directly, or passing the result of a comparison step that produced zero entity reports (e.g. all competitor resolutions failed and the caller did not fall back to the single-entity renderer).","commonSituations":"Comparison run where every competitor lookup returned empty and the caller forwarded the empty list instead of degrading to render_for_html. Programmatic use that builds entity_reports from a filter that removed everything.","solutions":["Ensure entity_reports contains at least the main topic's (label, Report) before calling.","If comparison yielded zero entities, fall back to the single-entity render_for_html(report) path.","Guard the caller: if not entity_reports, skip rendering or raise a clearer upstream error."],"exampleFix":"# before\nmd = render_for_html_comparison(entity_reports)  # entity_reports == []\n\n# after\nif not entity_reports:\n    md = render_for_html(main_report, save_path=save_path)\nelse:\n    md = render_for_html_comparison(entity_reports, save_path=save_path)","handlingStrategy":"validation","validationCode":"def safe_render_for_html_comparison(entity_reports, synthesis_md=None, save_path=None):\n    if not entity_reports:\n        raise ValueError(\"cannot render comparison: entity_reports is empty\")\n    return render_for_html_comparison(entity_reports, synthesis_md, save_path=save_path)","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Ensure at least the main topic's (label, Report) is in entity_reports before calling.","Fall back to the single-entity render_for_html when comparison discovery yields nothing.","Add an orchestrator-level assert that entity_reports is non-empty."],"tags":["validation","rendering","comparison"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}