{"record":{"id":"639f4bf96e3f7c35","repo":"TheAlgorithms/Python","slug":"invalid-operation-type-operation-op-type","errorCode":null,"errorMessage":"invalid operation type: {operation.op_type}","messagePattern":"invalid operation type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"machine_learning/automatic_differentiation.py","lineNumber":322,"sourceCode":"                if params[0] == param\n                else params[0].to_ndarray().T\n            )\n        if operation == OpType.DIV:\n            if params[0] == param:\n                return 1 / params[1].to_ndarray()\n            return -params[0].to_ndarray() / (params[1].to_ndarray() ** 2)\n        if operation == OpType.MATMUL:\n            return (\n                params[1].to_ndarray().T\n                if params[0] == param\n                else params[0].to_ndarray().T\n            )\n        if operation == OpType.POWER:\n            power = operation.other_params[\"power\"]\n            return power * (params[0].to_ndarray() ** (power - 1))\n\n        err_msg = f\"invalid operation type: {operation.op_type}\"\n        raise ValueError(err_msg)\n\n\nif __name__ == \"__main__\":\n    import doctest\n\n    doctest.testmod()\n","sourceCodeStart":304,"sourceCodeEnd":329,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/machine_learning/automatic_differentiation.py#L304-L329","documentation":"Raised in automatic_differentiation's backward-gradient helper when asked for the local gradient of an operation whose OpType is none of the handled cases (ADD, SUB, MUL, DIV, MATMUL, POWER). The reverse-mode differentiation dispatch is a chain of explicit if-checks; an unlisted operation falls through to this ValueError instead of silently returning a wrong derivative.","triggerScenarios":"Building a computational graph containing an OpType beyond the six supported ones (e.g. a newly added log/exp/sin node) and then requesting gradients, so the switch on operation reaches the fallthrough at the end.","commonSituations":"Extending the library with new operations but forgetting to add the derivative rule, or serializing/deserializing graphs whose op_type strings map to enum members the gradient code predates.","solutions":["Remove the unsupported operation from the graph or replace it with compositions of ADD/SUB/MUL/DIV/POWER/MATMUL.","If you control the library, add a branch for the missing OpType with its local derivative in this gradient function.","Print operation.op_type on the failing node to identify exactly which op is unhandled."],"exampleFix":"# before\nloss = Tensor.log(x)  # OpType.LOG, then .backward()\n\n# after\nloss = Tensor.power(x, 0.5)  # express via supported POWER op, then .backward()","handlingStrategy":"validation","validationCode":"SUPPORTED = {OpType.ADD, OpType.SUB, OpType.MUL, OpType.DIV, OpType.MATMUL, OpType.POWER}\nfor node in graph.nodes:\n    if node.op_type not in SUPPORTED:\n        raise ValueError(f\"op {node.op_type} has no gradient rule\")\nloss.backward()","typeGuard":"def has_gradient_support(op_type) -> bool:\n    return op_type in {OpType.ADD, OpType.SUB, OpType.MUL, OpType.DIV, OpType.MATMUL, OpType.POWER}","tryCatchPattern":"try:\n    gradients = backward(graph)\nexcept ValueError as e:\n    if \"invalid operation type\" in str(e):\n        raise NotImplementedError(f\"rewrite graph without unsupported op: {e}\") from e\n    raise","preventionTips":["Limit graphs to the six supported operations when you need gradients.","If extending the library, add derivative branches together with new OpTypes.","Validate the op set before running backward, not after."],"tags":["machine-learning","autodiff","unsupported-operation","gradient"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}