keras-team/keras · error · ValueError
Tensor {tensor} from operation '{operation.name}' is part of
Error message
Tensor {tensor} from operation '{operation.name}' is part of a cycle. What it means
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.
Source
Thrown at keras/src/ops/function.py:462
return
node = operation._inbound_nodes[node_index]
# Don't repeat work for shared subgraphs
if node in finished_nodes:
return
# If this tensor is one of the declared inputs and its producing
# operation is not an InputLayer, stop traversal here. The operation
# that produced this tensor is outside the Function's graph.
flat_inputs = tree.flatten(inputs)
if not node.is_input and tensor in flat_inputs:
finished_nodes.add(node)
return
# Prevent cycles.
if node in nodes_in_progress:
raise ValueError(
f"Tensor {tensor} from operation '{operation.name}' is part of a "
"cycle."
)
# Store the traversal order for operation sorting.
if operation not in operation_indices:
operation_indices[operation] = len(operation_indices)
# Propagate to all previous tensors connected to this node.
nodes_in_progress.add(node)
if not node.is_input:
for input_tensor in node.input_tensors:
_build_map_helper(
inputs,
input_tensor,
finished_nodes,
nodes_in_progress,
nodes_in_decreasing_depth,View on GitHub (pinned to 7a34a03db6)
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
Example fix
# before out = block(x) out = layers.Add()([out, out_prev]) # out_prev derived from out -> cycle # after out = block(x) out = layers.Add()([out, skip_from_input]) # skip comes from inputs/earlier node
Defensive patterns
Strategy: validation
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Output with path `{path}` is not connected to `inputs`
- Graph disconnected: cannot find parent for tensor {x} at ope
- The name "{name}" is used {all_names.count(name)} times in t
- Unknown activation function '{activation}' cannot be seriali
- Could not interpret activation function identifier: {identif
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/458633a382eca5d9.
Report an issue: GitHub.