{"record":{"id":"643b5e9180755d1a","repo":"ScrapeGraphAI/Scrapegraph-ai","slug":"comparison-result-missing-differences-key","errorCode":null,"errorMessage":"comparison_result missing 'differences' key","messagePattern":"comparison_result missing 'differences' key","errorType":"error_code","errorClass":"InvalidStateError","httpStatus":null,"severity":"error","filePath":"scrapegraphai/utils/code_error_analysis.py","lineNumber":312,"sourceCode":"        >>> state = {\n            'generated_code': 'def add(a, b): return a + b'\n        }\n        >>> comparison_result = {\n            'differences': ['Missing docstring', 'No type hints'],\n            'explanation': 'The code is missing documentation'\n        }\n        >>> analysis = semantic_focused_analysis(state, comparison_result, mock_llm)\n    \"\"\"\n    try:\n        # Validate state using Pydantic model\n        validated_state = CodeAnalysisState(\n            generated_code=state.get(\"generated_code\", \"\"),\n            errors=state.get(\"errors\", {}),\n        )\n\n        # Validate comparison_result\n        if \"differences\" not in comparison_result:\n            raise InvalidStateError(\"comparison_result missing 'differences' key\")\n        if \"explanation\" not in comparison_result:\n            raise InvalidStateError(\"comparison_result missing 'explanation' key\")\n\n        # Create prompt template and chain\n        prompt = PromptTemplate(\n            template=get_optimal_analysis_template(\"semantic\"),\n            input_variables=[\"generated_code\", \"differences\", \"explanation\"],\n        )\n        chain = prompt | llm_model | StrOutputParser()\n\n        # Execute chain with validated inputs\n        return chain.invoke(\n            {\n                \"generated_code\": validated_state.generated_code,\n                \"differences\": json.dumps(comparison_result[\"differences\"], indent=2),\n                \"explanation\": comparison_result[\"explanation\"],\n            }\n        )","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/532dfffbf6ee823a6c9cf8cfedc24a93bf026780/scrapegraphai/utils/code_error_analysis.py#L294-L330","documentation":"semantic_focused_analysis requires the comparison_result dict to contain a 'differences' key; this InvalidStateError is thrown upfront when it is absent. comparison_result is expected to come from a prior semantic comparison step (LLM answer compare).","triggerScenarios":"Calling semantic_comparison_loop / semantic_focused_analysis(state, comparison_result, llm_model) where comparison_result was built by hand or by a comparison step that did not include 'differences' (e.g. LLM output parsing dropped it).","commonSituations":"Passing the raw output of an LLM comparison without parsing it into {differences, explanation}; a comparison node returning a different key layout after a version change; empty dict passed while testing.","solutions":["Ensure comparison_result is a dict with both 'differences' and 'explanation' keys before calling","If it comes from an LLM comparison step, parse/normalize its output (e.g. json.loads + key check) first","Upgrade both producer and consumer together so the key contract stays in sync"],"exampleFix":"# before\nsemantic_focused_analysis(state, llm_comparison_output, llm)\n# after\ncomparison = {\"differences\": llm_comparison_output.get(\"differences\", []), \"explanation\": llm_comparison_output.get(\"explanation\", \"\")}\nsemantic_focused_analysis(state, comparison, llm)","handlingStrategy":"type-guard","validationCode":"if not isinstance(comparison_result, dict) or \"differences\" not in comparison_result:\n    comparison_result = {\"differences\": [], \"explanation\": str(comparison_result)}","typeGuard":"def is_valid_comparison(cr) -> bool:\n    return isinstance(cr, dict) and \"differences\" in cr and \"explanation\" in cr","tryCatchPattern":"from scrapegraphai.utils.code_error_analysis import InvalidStateError\ntry:\n    semantic_focused_analysis(state, comparison_result, llm_model)\nexcept InvalidStateError as e:\n    if \"differences\" in str(e):\n        comparison_result.setdefault(\"differences\", [])\n    raise","preventionTips":["Normalize comparison output to {differences, explanation} before calling","Parse LLM comparison output as JSON and validate keys","Pin producer/consumer to the same package version"],"tags":["state","comparison-result","semantic-analysis","key-check"],"backgroundTag":"state-validation-failed","analyzedSha":"532dfffbf6ee823a6c9cf8cfedc24a93bf026780","analyzedAt":"2026-08-28T15:19:38.821Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}