{"record":{"id":"e94ae41643ee9f6d","repo":"datawhalechina/hello-agents","slug":"tool-decompose-only-accepts-theorems-with-parame","errorCode":null,"errorMessage":"Tool 'decompose' only accepts theorems with parameters!","messagePattern":"Tool 'decompose' only accepts theorems with parameters!","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/BitSecret-GPSAgent/src/gps/symbolic_solver.py","lineNumber":1362,"sourceCode":"                fact_id, goal_ids = self._add_conclusion(theorem_gdl, replace, premise_ids[i], operation_id)\n                all_goal_ids.update(goal_ids)\n\n            self._check_goals(all_goal_ids)\n\n            if len(all_goal_ids) == 0:\n                return f\"定理'{theorem_name}'执行成功，但没有推导出新的结论。\"\n\n            result = f\"定理'{theorem_name}'执行成功，以下为问题的状态更新。\\n\"\n            return result + self._get_update(old_fact_id, old_goal_id, old_goal_status)\n\n    def decompose(self, theorem):\n        old_fact_id = len(self.facts)\n        old_goal_id = len(self.goals)\n        old_goal_status = self.status_of_goal.copy()\n        theorem_name, theorem_paras = self._parse_theorem(theorem)\n\n        if theorem_paras is None:\n            raise ValueError(\"Tool 'decompose' only accepts theorems with parameters!\")\n\n        theorem_gdl = self.parsed_gdl['Theorems'][theorem_name]\n        replace = dict(zip(theorem_gdl['paras'], theorem_paras))\n        predicate, instance = theorem_gdl['conclusion']  # generate conclusion\n        if predicate == \"Eq\":\n            instance = self._adjust_expr(replace_expr(instance, replace))\n            if instance is None or len(instance.free_symbols) == 0:\n                return f\"使用定理'{theorem}'分解目标{_anti_parse_fact((predicate, instance))}失败，目标无需分解或非法。\"\n        else:\n            instance = tuple(replace_paras(instance, replace))\n        goal = _anti_parse_fact((predicate, instance))\n\n        passed, result = self._pass_algebraic_constraints(theorem_gdl, replace)  # ac checks\n        if not passed:\n            return f\"使用定理'{theorem}'分解目标{goal}失败，\" + result\n\n        passed, result = self._pass_geometric_constraints(predicate, instance)  # ee checks\n        if not passed:","sourceCodeStart":1344,"sourceCodeEnd":1380,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/BitSecret-GPSAgent/src/gps/symbolic_solver.py#L1344-L1380","documentation":"decompose() uses _parse_theorem() to split the theorem into name and parameters, then requires parameters: goal decomposition works by substituting explicit parameters into the theorem's conclusion to build a new sub-goal, which is meaningless without a binding. Unlike apply(), decompose() raises ValueError (not Exception) when theorem_paras is None.","triggerScenarios":"Calling solver.decompose('some_theorem') with no parenthesized parameter list — note that '()' or whitespace-only params also parse to an empty string and become None.","commonSituations":"Agents reusing the bare-name style that apply() accepts for some theorems; passing a theorem string whose parentheses were stripped or never included.","solutions":["Call decompose with explicit parameters: solver.decompose('midline(A,B,C)').","Remember parameters must be single uppercase letters and commas only, matching the GDL arity (errors 121/122 apply).","If you only want to run a theorem forward, use apply() instead of decompose()."],"exampleFix":"# before\nsolver.decompose('pythagorean_theorem')\n\n# after\nsolver.decompose('pythagorean_theorem(A,B,C)')","handlingStrategy":"validation","validationCode":"def can_decompose(theorem):\n    return '(' in theorem and any(c.isupper() for c in theorem.split('(', 1)[1])","typeGuard":null,"tryCatchPattern":"try:\n    solver.decompose(theorem)\nexcept ValueError as e:\n    if 'only accepts theorems with parameters' in str(e):\n        theorem = f\"{theorem.split('(')[0]}({','.join(points)})\"  # bind and retry","preventionTips":["Never call decompose() with a bare theorem name — always include '(A,B,...)'.","Route forward inference to apply() and goal splitting to decompose() explicitly in agent logic.","Catch ValueError separately from Exception: decompose raises ValueError while apply/decompose parse errors raise Exception."],"tags":["geometry","symbolic-solver","decompose","valueerror"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}