{"record":{"id":"b99e8b2e6e37c11f","repo":"nexu-io/open-design","slug":"render-comparison-multi-requires-at-least-one-repo","errorCode":null,"errorMessage":"render_comparison_multi requires at least one report","messagePattern":"render_comparison_multi requires at least one report","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"design-templates/last30days/scripts/lib/render.py","lineNumber":581,"sourceCode":"    save_path: str | None = None,\n) -> str:\n    \"\"\"Render N (entity, Report) pairs as a single comparison output.\n\n    Reuses _render_comparison_scaffold for the synthesis table and emits\n    per-entity evidence sections inside one EVIDENCE FOR SYNTHESIS envelope.\n    The single-Report render_compact path is unchanged.\n\n    Args:\n        entity_reports: Ordered (label, Report) pairs. The first pair is the\n            user's main topic; the remainder are discovered/explicit competitors.\n        cluster_limit: Max clusters to surface per entity (kept lower than the\n            single-entity default to keep N-way comparisons readable).\n        fun_level: Same fun-level knob as render_compact, applied to each\n            entity's best-takes block.\n        save_path: Optional save-path display string for the footer.\n    \"\"\"\n    if not entity_reports:\n        raise ValueError(\"render_comparison_multi requires at least one report\")\n\n    entities = [label for label, _ in entity_reports]\n    main_label, main_report = entity_reports[0]\n    synthesized_topic = \" vs \".join(entities)\n\n    lines: list[str] = [\n        *_render_badge(),\n        f\"# last30days v3.0.0: {synthesized_topic}\",\n        \"\",\n        *_assistant_safety_lines(),\n        f\"- Comparison mode: {len(entities)} entities ({', '.join(entities)})\",\n        f\"- Date range: {main_report.range_from} to {main_report.range_to}\",\n        \"\",\n    ]\n\n    aggregated_warnings: list[str] = []\n    for label, report in entity_reports:\n        aggregated_warnings.extend(f\"[{label}] {w}\" for w in report.warnings)","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/design-templates/last30days/scripts/lib/render.py#L563-L599","documentation":"render_comparison_multi requires at least one entity report because it reads main_label/main_report from entity_reports[0] and joins entity labels with ' vs '. The guard prevents an IndexError and a meaningless empty-title render.","triggerScenarios":"Calling render_comparison_multi([]). Typically reached when the comparison discovery step returned no entities (all competitors unresolved) and the caller did not downgrade to the single-entity render_compact path.","commonSituations":"Comparison run with zero competitor matches. Filter that drops every entity before render. Caller reused the multi-renderer for a single entity but passed an empty list by mistake.","solutions":["Pass at least the main (label, Report) pair into render_comparison_multi.","Downgrade to render_compact(report) when only one entity is available.","Validate entity_reports is non-empty at the comparison orchestrator before dispatching to the renderer."],"exampleFix":"# before\nout = render_comparison_multi(entity_reports)  # []\n\n# after\nif len(entity_reports) >= 2:\n    out = render_comparison_multi(entity_reports)\nelif len(entity_reports) == 1:\n    out = render_compact(entity_reports[0][1])\nelse:\n    raise ValueError(\"no entities to render\")","handlingStrategy":"validation","validationCode":"def safe_render_comparison_multi(entity_reports, **kwargs):\n    if not entity_reports:\n        raise ValueError(\"cannot render multi comparison: entity_reports is empty\")\n    return render_comparison_multi(entity_reports, **kwargs)","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Branch on len(entity_reports): >=2 -> multi, ==1 -> compact, 0 -> error/skip.","Validate entity_reports at the comparison orchestrator before dispatch.","Make discovery failures explicit rather than silently producing an empty list."],"tags":["validation","rendering","comparison"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}