{"record":{"id":"7ce490942340529e","repo":"HKUDS/DeepTutor","slug":"invalid-concept-graph-payload-exc","errorCode":null,"errorMessage":"invalid concept_graph payload: {exc}","messagePattern":"invalid concept_graph payload: (.+?)","errorType":"exception","errorClass":"GenerationFailure","httpStatus":null,"severity":"error","filePath":"deeptutor/book/blocks/concept_graph.py","lineNumber":98,"sourceCode":"    return \"\\n\".join(lines)\n\n\nclass ConceptGraphGenerator(BlockGenerator):\n    block_type = BlockType.CONCEPT_GRAPH\n\n    async def _generate(\n        self, ctx: BlockContext\n    ) -> tuple[dict[str, Any], list[SourceAnchor], dict[str, Any]]:\n        raw = ctx.extra.get(\"concept_graph\") or ctx.block.params.get(\"concept_graph\")\n        if raw is None:\n            raise GenerationFailure(\"concept_graph payload missing from BlockContext.extra\")\n        if isinstance(raw, ConceptGraph):\n            graph = raw\n        elif isinstance(raw, dict):\n            try:\n                graph = ConceptGraph.model_validate(raw)\n            except Exception as exc:\n                raise GenerationFailure(f\"invalid concept_graph payload: {exc}\") from exc\n        else:\n            raise GenerationFailure(f\"unexpected concept_graph payload type: {type(raw).__name__}\")\n\n        chapters_index = ctx.extra.get(\"chapter_index\") or []\n        if not isinstance(chapters_index, list):\n            chapters_index = []\n\n        mermaid_src = render_mermaid(graph)\n\n        # Build a node→chapter lookup for the interactive sidebar.\n        node_to_chapter: dict[str, str] = {}\n        for n in graph.nodes:\n            if n.chapter_id:\n                node_to_chapter[n.id] = n.chapter_id\n\n        return (\n            {\n                \"render_type\": \"concept_graph\",","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/book/blocks/concept_graph.py#L80-L116","documentation":"A `concept_graph` payload WAS supplied as a dict, but `ConceptGraph.model_validate(raw)` rejected it — schema validation failed (missing required fields, wrong types, bad edge/node shapes). The Pydantic error text is chained into the message.","triggerScenarios":"Passing a hand-built or externally serialized dict in `extra['concept_graph']` / block params that doesn't satisfy the ConceptGraph schema — missing node ids, edges referencing unknown nodes, wrong field types, JSON round-tripped through a lossy step.","commonSituations":"Feeding LLM-generated or user-edited graph JSON; version skew where ConceptGraph gained required fields; pipelines that build dicts ad hoc instead of using the model.","solutions":["Read the chained validation error to see the exact failing field","Construct payloads via the ConceptGraph model itself (model_validate on your validated dict, or build with the class) so type errors surface early","Add a Pydantic validation step at your pipeline boundary before handing data to the block","Pin/align versions so schema fields match what your producer emits"],"exampleFix":"# before\nctx.extra[\"concept_graph\"] = {\"nodes\": \"n1\", \"edges\": []}\n\n# after\nfrom deeptutor... import ConceptGraph\ngraph = ConceptGraph.model_validate({\"nodes\": [...], \"edges\": [...]})\nctx.extra[\"concept_graph\"] = graph","handlingStrategy":"type-guard","validationCode":"from pydantic import ValidationError\ntry:\n    ConceptGraph.model_validate(payload)\nexcept ValidationError as e:\n    fix_or_reject(payload, e.errors())","typeGuard":"def is_valid_graph_payload(raw) -> bool:\n    if isinstance(raw, ConceptGraph):\n        return True\n    if isinstance(raw, dict):\n        try:\n            ConceptGraph.model_validate(raw)\n            return True\n        except Exception:\n            return False\n    return False","tryCatchPattern":"from deeptutor.book.compiler import GenerationFailure\ntry:\n    await cg_gen._generate(ctx)\nexcept GenerationFailure as e:\n    if \"invalid concept_graph payload\" in str(e):\n        ctx.extra[\"concept_graph\"] = ConceptGraph.model_validate(sanitized(raw))\n        return await cg_gen._generate(ctx)\n    raise","preventionTips":["Build payloads with the ConceptGraph model instead of raw dicts","Validate external/LLM-produced graph JSON at your pipeline boundary","Pin DeepTutor versions so producer and schema stay aligned"],"tags":["pydantic","schema-validation","concept-graph"],"backgroundTag":"schema-validation-failed","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}