{"record":{"id":"458633a382eca5d9","repo":"keras-team/keras","slug":"tensor-tensor-from-operation-operation-name","errorCode":null,"errorMessage":"Tensor {tensor} from operation '{operation.name}' is part of a cycle.","messagePattern":"Tensor (.+?) from operation '(.+?)' is part of a cycle\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/ops/function.py","lineNumber":462,"sourceCode":"        return\n\n    node = operation._inbound_nodes[node_index]\n\n    # Don't repeat work for shared subgraphs\n    if node in finished_nodes:\n        return\n\n    # If this tensor is one of the declared inputs and its producing\n    # operation is not an InputLayer, stop traversal here. The operation\n    # that produced this tensor is outside the Function's graph.\n    flat_inputs = tree.flatten(inputs)\n    if not node.is_input and tensor in flat_inputs:\n        finished_nodes.add(node)\n        return\n\n    # Prevent cycles.\n    if node in nodes_in_progress:\n        raise ValueError(\n            f\"Tensor {tensor} from operation '{operation.name}' is part of a \"\n            \"cycle.\"\n        )\n\n    # Store the traversal order for operation sorting.\n    if operation not in operation_indices:\n        operation_indices[operation] = len(operation_indices)\n\n    # Propagate to all previous tensors connected to this node.\n    nodes_in_progress.add(node)\n    if not node.is_input:\n        for input_tensor in node.input_tensors:\n            _build_map_helper(\n                inputs,\n                input_tensor,\n                finished_nodes,\n                nodes_in_progress,\n                nodes_in_decreasing_depth,","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/ops/function.py#L444-L480","documentation":"While recursively mapping the symbolic graph, _build_map_helper tracks nodes currently being traversed. Encountering a node that is already in progress means the tensor depends on itself — a cycle — which a feed-forward function graph cannot represent, so construction aborts.","triggerScenarios":"Wiring a layer's output back into its own input chain, e.g. y = layer(layer(x) ... y), or building a recurrent/feedback structure with plain functional ops instead of a proper RNN cell; aliasing bugs where a variable is overwritten and feeds itself.","commonSituations":"Attempting custom recurrence with the functional API; variable shadowing in long build functions (out = f(out) before out is defined from inputs); copy-paste wiring that connects a block's output to its own input.","solutions":["Inspect the operation named in the message and break the feedback loop: its input must come from the function inputs or earlier nodes only","For recurrent behavior, use keras.layers.RNN with a cell, or a keras.ops.custom_op/python function with scan-style loops instead of the symbolic graph","Check for accidental self-assignment/shadowing of the tensor variable during graph construction"],"exampleFix":"# before\nout = block(x)\nout = layers.Add()([out, out_prev])  # out_prev derived from out -> cycle\n\n# after\nout = block(x)\nout = layers.Add()([out, skip_from_input])  # skip comes from inputs/earlier node","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never wire a block's output back into its own input chain in the functional API","Use keras.layers.RNN for recurrence instead of manual feedback","Review variable assignments in long build functions for accidental self-dependency"],"tags":["keras","graph","cycle","recurrent"],"backgroundTag":"cyclic-computation-graph","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}