Possible Expression Engine Bug: Resolver State Depends on Dependency Traversal
- August 30, 2026
- 3 replies
- 142 views
Hi,
I've been investigating a reproducible issue involving transform expressions and property[index].
What initially looked like a simple circular-dependency edge case now appears to be something more fundamental: the resolved state of the graph seems to depend on which dependency branch is traversed.
Adobe After Effects 25.6.4
Windows 11
Setup
Layer: property index
Anchor Point:
thisLayer.scale[0];
thisLayer.rotation[0];
thisLayer.opacity[0];
thisLayer.position[0];
thisLayer.anchorPoint[0];
[11,22]
Position:
thisLayer.anchorPoint
Scale:
thisLayer.anchorPoint
Rotation:
thisLayer.anchorPoint[0]
Opacity:
thisLayer.anchorPoint[0]
Observation
Depending on layer arrangement and evaluation order, the graph can expose a mixture of expression values and pre-expression values.
For example, the Transform panel may show:
Anchor Point = 11,22
Position = 11,22
Scale = 40,80
Rotation = 40
Opacity = 40
while external reads may report:
Anchor Point = 11,22
Position = 40,80
Scale = 40,80
Rotation = 40
Opacity = 11
In other words, different access paths appear to observe different states of the same dependency graph.
Stronger Repro
The most surprising result is that the final expression output does not seem to matter.
For example:
if (random() < .5)
thisLayer.scale[0];
else
thisLayer.position[1];
0;
The expression always returns:
0
However, simply touching different dependency branches can change the resolved state observed elsewhere in the graph.
The referenced values are discarded and never contribute to the final output.
Additional Test
This expression:
switch (timeToFrames(time) % 4){
case 0: throw(thisLayer.scale[0]);
case 1: throw(thisLayer.position[1]);
case 2: throw(thisLayer.rotation);
case 3: throw(thisLayer.opacity);
}
produces different outputs depending on which dependency branch is selected.
This suggests that the resolver outcome is affected by traversal path rather than only by the graph itself.
Why This Seems Wrong
I would expect:
Result = f(graph)
Instead, the observed behavior looks more like:
Result = f(graph, traversal path)
where simply visiting a different dependency branch can change the state produced by the resolver.
The most surprising part is that these branch references do not need to contribute to the final returned value.
Core Question
Is dependency traversal intentionally allowed to influence cycle resolution for transform graphs involving property[index]?
Or does this indicate a resolver bug where different traversal paths can lead to different graph states, causing properties to alternate between expression values and pre-expression values?
