{"record":{"id":"192d7777279e0229","repo":"HKUDS/DeepTutor","slug":"concept-graph-payload-missing-from-blockcontext-ex","errorCode":null,"errorMessage":"concept_graph payload missing from BlockContext.extra","messagePattern":"concept_graph payload missing from BlockContext\\.extra","errorType":"exception","errorClass":"GenerationFailure","httpStatus":null,"severity":"error","filePath":"deeptutor/book/blocks/concept_graph.py","lineNumber":91,"sourceCode":"    arrow_for = {\"depends_on\": \"-->\", \"extends\": \"==>\", \"related\": \"-.->\"}\n    for edge in graph.edges:\n        if edge.src not in id_map or edge.dst not in id_map:\n            continue\n        arrow = arrow_for.get(edge.relation, \"-->\")\n        lines.append(f\"  {id_map[edge.src]} {arrow} {id_map[edge.dst]}\")\n\n    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] = {}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/book/blocks/concept_graph.py#L73-L109","documentation":"The concept_graph block needs a ConceptGraph payload and looks it up in `ctx.extra['concept_graph']` then `ctx.block.params['concept_graph']`; when neither is present it fails generation with this message.","triggerScenarios":"Compiling a book whose outline contains a `concept_graph` block while the caller (pipeline/compiler) forgot to inject the graph into BlockContext.extra, and the block params don't carry it either — e.g. custom pipelines constructing BlockContext by hand.","commonSituations":"Building your own generation pipeline and passing a bare BlockContext; reordering compiler stages so graph extraction runs after block generation; serializing/deserializing contexts and dropping `extra`.","solutions":["Pass the ConceptGraph when building the context: put it in extra under 'concept_graph' or into block params","If driving the standard compiler, ensure the concept-graph extraction stage runs before block generation","If a one-off render, construct `ConceptGraph(...)` and inject it explicitly"],"exampleFix":"# before\nctx = BlockContext(block=block, language=\"en\", extra={})\n\n# after\nctx = BlockContext(\n    block=block,\n    language=\"en\",\n    extra={\"concept_graph\": my_concept_graph},\n)","handlingStrategy":"validation","validationCode":"if \"concept_graph\" not in ctx.extra and \"concept_graph\" not in (ctx.block.params or {}):\n    raise ValueError(\"inject concept_graph before generating concept_graph blocks\")","typeGuard":"def has_graph_payload(ctx) -> bool:\n    return ctx.extra.get(\"concept_graph\") is not None or \\\n           ctx.block.params.get(\"concept_graph\") is not None","tryCatchPattern":"from deeptutor.book.compiler import GenerationFailure\ntry:\n    await cg_gen._generate(ctx)\nexcept GenerationFailure as e:\n    if \"payload missing\" in str(e):\n        ctx.extra[\"concept_graph\"] = build_graph(chapters)\n        return await cg_gen._generate(ctx)\n    raise","preventionTips":["Run graph extraction before block generation in custom pipelines","Always populate BlockContext.extra when constructing contexts by hand"],"tags":["concept-graph","context","pipeline","validation"],"backgroundTag":"missing-context-payload","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}