{"record":{"id":"7752d1ded079126d","repo":"FoundationAgents/MetaGPT","slug":"invalid-python-code","errorCode":null,"errorMessage":"Invalid python code","messagePattern":"Invalid python code","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"metagpt/utils/common.py","lineNumber":139,"sourceCode":"            # Convert string representation of list to a Python list using ast.literal_eval.\n            tasks = ast.literal_eval(tasks_list_str)\n        else:\n            tasks = text.split(\"\\n\")\n        return tasks\n\n    @staticmethod\n    def parse_python_code(text: str) -> str:\n        for pattern in (r\"(.*?```python.*?\\s+)?(?P<code>.*)(```.*?)\", r\"(.*?```python.*?\\s+)?(?P<code>.*)\"):\n            match = re.search(pattern, text, re.DOTALL)\n            if not match:\n                continue\n            code = match.group(\"code\")\n            if not code:\n                continue\n            with contextlib.suppress(Exception):\n                ast.parse(code)\n                return code\n        raise ValueError(\"Invalid python code\")\n\n    @classmethod\n    def parse_data(cls, data):\n        block_dict = cls.parse_blocks(data)\n        parsed_data = {}\n        for block, content in block_dict.items():\n            # 尝试去除code标记\n            try:\n                content = cls.parse_code(text=content)\n            except Exception:\n                # 尝试解析list\n                try:\n                    content = cls.parse_file_list(text=content)\n                except Exception:\n                    pass\n            parsed_data[block] = content\n        return parsed_data\n","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/utils/common.py#L121-L157","documentation":"OutputParser.parse_python_code in metagpt/utils/common.py tries two DOTALL regexes to strip markdown fences and extract a python code block, validating each candidate with ast.parse. If neither pattern yields a non-empty snippet that parses as valid Python syntax, it raises ValueError('Invalid python code').","triggerScenarios":"Passing prose with no code; passing fenced code whose body has a syntax error (ast.parse fails); a response truncated mid-code by max_tokens; code containing unclosed triple quotes or brackets; text where the '```python' fence is never closed.","commonSituations":"LLM output got cut off before the closing fence, leaving half a function that fails ast.parse; model emits pseudo-code or shell commands instead of python; the caller feeds arbitrary text into a method that assumes an LLM code response.","solutions":["Log the input text and run ast.parse on it manually to find the exact syntax error location.","If truncated, increase max_tokens or shrink the prompt and regenerate.","Ensure the code sits after a '```python' fence and is syntactically complete.","If you already hold raw code without fences, skip this parser and use the code string directly."],"exampleFix":"# before\nOutputParser.parse_python_code('def f(:')  # raises Invalid python code\n\n# after\nOutputParser.parse_python_code('```python\\ndef f():\\n    pass\\n```')","handlingStrategy":"validation","validationCode":"import ast\n\ndef is_parseable_python(text: str) -> bool:\n    try:\n        ast.parse(text)\n        return True\n    except SyntaxError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    code = OutputParser.parse_python_code(text)\nexcept ValueError:\n    # regenerate with higher max_tokens; log text for diagnosis","preventionTips":["Watch for truncation: an unclosed fence usually means max_tokens was hit.","Ask the model for complete, syntactically valid python in one fenced block."],"tags":["metagpt","llm-output","parsing","ast","syntax-error"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}