FLX-1007¶
dependency cycle cannot be resolved: orderRouter -> riskCheck -> positionStore
| Severity | ERROR |
| Category | GRAPH_MODEL |
| Element | CYCLE |
The rule¶
The dependency graph must be acyclic.
Why the compiler says this¶
Fluxtion dispatches in topological order, computed once at build time. A cycle has no such order — every node in it would have to run before itself — so there is no dispatch sequence to generate.
How to fix it¶
Break the cycle at whichever reference is not a trigger: mark it @NoTriggerReference (import com.telamin.fluxtion.runtime.annotations.NoTriggerReference) so the node still reads its parent's data without depending on it for ordering, or invert the edge with @PushReference.
Example¶
Both examples are compiled and put through a real Fluxtion.compile on every build, so the first is guaranteed to produce this diagnostic and the second to build cleanly. Note that the failing example is valid Java — javac is happy, and Fluxtion refuses it for its own reasons.
The code that causes it¶
package com.telamin.fluxtion.builder.diagnostic.examples;
import com.telamin.fluxtion.builder.generation.config.EventProcessorConfig;
import com.telamin.fluxtion.runtime.annotations.OnEventHandler;
import com.telamin.fluxtion.runtime.annotations.OnTrigger;
/** FLX-1007 — two nodes that each depend on the other. */
public class Flx1007Failing {
public static class RiskCheck {
// RiskCheck reads OrderRouter…
public OrderRouter router;
@OnEventHandler
public boolean onOrder(String order) {
return true;
}
}
public static class OrderRouter {
// …and OrderRouter reads RiskCheck. There is no order that satisfies both.
private final RiskCheck risk;
public OrderRouter(RiskCheck risk) {
this.risk = risk;
}
@OnTrigger
public boolean onRisk() {
return true;
}
}
public static void graph(EventProcessorConfig config) {
RiskCheck risk = new RiskCheck();
OrderRouter router = new OrderRouter(risk);
risk.router = router;
config.addNode(risk, "riskCheck");
config.addNode(router, "orderRouter");
}
}
The code that fixes it¶
package com.telamin.fluxtion.builder.diagnostic.examples;
import com.telamin.fluxtion.builder.generation.config.EventProcessorConfig;
import com.telamin.fluxtion.runtime.annotations.OnEventHandler;
import com.telamin.fluxtion.runtime.annotations.OnTrigger;
/** FLX-1007 fixed — the dependency runs one way. */
public class Flx1007Fixed {
public static class RiskCheck {
// The back-reference is gone: risk is upstream, and does not read what it feeds.
@OnEventHandler
public boolean onOrder(String order) {
return true;
}
}
public static class OrderRouter {
private final RiskCheck risk;
public OrderRouter(RiskCheck risk) {
this.risk = risk;
}
@OnTrigger
public boolean onRisk() {
return true;
}
}
public static void graph(EventProcessorConfig config) {
RiskCheck risk = new RiskCheck();
config.addNode(risk, "riskCheck");
config.addNode(new OrderRouter(risk), "orderRouter");
}
}
Which builds raise it¶
Every build path — interpreted, in-process and AOT alike.
Reading it programmatically¶
This diagnostic is also written to the machine-readable report — the opt-in sidecar (-Dfluxtion.diagnostics.sidecar=true), or FluxtionDiagnostics.capture(...) for a caller that wants the objects:
{
"code": "FLX-1007",
"severity": "ERROR",
"category": "GRAPH_MODEL",
"element": { "kind": "CYCLE", … }
}
Select findings by severity, never by position: a failing build's report also contains any warnings it found, and diagnostics[0] is not the cause of the failure.
This page is generated from the compiler itself, so the wording above is exactly what a build emits. Do not edit it by hand — it is overwritten whenever the diagnostics are regenerated.