pub enum SetDepsError {
SelfDependency {
n: NodeId,
},
WouldCreateCycle {
n: NodeId,
added_dep: NodeId,
path: Vec<NodeId>,
},
UnknownNode(NodeId),
NotComputeNode(NodeId),
TerminalNode {
n: NodeId,
},
TerminalDep {
n: NodeId,
dep: NodeId,
},
ReentrantOnFiringNode {
n: NodeId,
},
PartitionMigrationDuringFire {
n: NodeId,
firing: NodeId,
},
}Expand description
Errors returnable by Core::set_deps.
Per ~/src/graphrefly-ts/docs/research/rewire-design-notes.md and the
Phase 13.8 Q1 lock:
SelfDependency—n in newDeps(self-loops are pathological without explicit fixed-point semantics, which GraphReFly does not provide).WouldCreateCycle { path }— adding the new edge would create a cycle. Thepathfield reports the offending dep chain for debuggability.UnknownNode/NotComputeNode— invariant violations from the caller.TerminalNode—nitself has emitted COMPLETE/ERROR; rewiring a terminal stream is a category error (terminal is one-shot at this layer; recovery is the resubscribable path on a fresh subscribe).TerminalDep— a newly-added dep is terminal AND not resubscribable. Resubscribable terminal deps are accepted because the subscribe path resets their lifecycle. Non-resubscribable terminal deps would deliver their already-emitted terminal directly ton’sdep_terminalsslot, which is rarely intended.
Variants§
SelfDependency
n appeared in new_deps (self-loop rejection).
WouldCreateCycle
Adding the new dep would create a cycle. path is the chain
[added_dep, ..., n] reachable via existing deps.
UnknownNode(NodeId)
NotComputeNode(NodeId)
TerminalNode
n itself has terminated (COMPLETE / ERROR). Rewiring a terminal node
is rejected — the stream has ended at this layer. To recover, mark
the node resubscribable before terminate; a fresh subscribe will then
reset its lifecycle.
TerminalDep
A newly-added dep is terminal AND non-resubscribable. Per Phase 13.8 Q1, this is rejected; resubscribable terminal deps are allowed because the subscribe path resets them when activated. Already-present terminal deps are unaffected (their terminal status was accepted at the time they terminated).
ReentrantOnFiringNode
n itself is currently mid-fire — a user fn for n re-entered Core
via set_deps(n, ...) from inside n’s own invoke_fn /
project_each / predicate_each / etc. Phase 1 of the dispatcher
snapshotted dep_handles BEFORE the lock-released callback; the
callback returning a tracked set indexed against THAT ordering
would corrupt indices if the rewire re-orders deps mid-fire.
Rejected to preserve the dynamic-tracked-indices invariant (D1).
Workaround: schedule the rewire from a different node’s fn (via
Core::emit on a state node and observing the emit downstream),
or perform the rewire after the wave completes (e.g. from a sink
callback that is itself outside any fn-fire scope).
Slice F (2026-05-07) — A6.
PartitionMigrationDuringFire
set_deps(n, ...) would trigger a partition migration (union or
split in the per-subgraph union-find registry) that affects the
partition of a node currently mid-fire on this thread. Distinct
from Self::ReentrantOnFiringNode: that variant rejects
set_deps(n, ...) where n itself is firing; this variant
rejects set_deps(n, ...) on some OTHER node whose union/split
shifts a firing node’s partition root mid-wave.
Why this matters: Y1’s wave engine holds an
Arc<crate::subgraph::SubgraphLockBox> for the firing node’s
partition for the wave’s duration. A union mid-wave swaps the
box-identity for one of the two affected partitions; a split
(Y1+ post-Phase-F) extracts a fresh box for the orphan side.
Either way the held Arc would diverge from the registry’s
current root for that partition, so the wave would lose
serialization against the box’s true partition mid-flight.
Per SESSION-rust-port-d3-per-subgraph-parallelism.md
Q3 = (a-strict): mid-wave migration is rejected at edge-mutation
time. If a real consumer surfaces pressure to support mid-wave
migration, lift via state-migration logic in a follow-up — but
the v1 contract is “the partition a wave runs in cannot change
shape mid-flight.”
n is the node whose set_deps was rejected; firing is the
concretely-identified firing node whose partition would be
migrated. Workaround: schedule the rewire outside the wave
(e.g. emit a state-change that triggers set_deps from a sink
callback running post-flush).
Slice Y1 (D3 / D091, 2026-05-08).
Trait Implementations§
Source§impl Clone for SetDepsError
impl Clone for SetDepsError
Source§fn clone(&self) -> SetDepsError
fn clone(&self) -> SetDepsError
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SetDepsError
impl Debug for SetDepsError
Source§impl Display for SetDepsError
impl Display for SetDepsError
Source§impl Error for SetDepsError
impl Error for SetDepsError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl PartialEq for SetDepsError
impl PartialEq for SetDepsError
Source§fn eq(&self, other: &SetDepsError) -> bool
fn eq(&self, other: &SetDepsError) -> bool
self and other values to be equal, and is used by ==.