Selkie.git | docs/api/ | X--Selkie--WidgetCycle.md
NAME
====
X::Selkie::WidgetCycle - thrown when a widget's parent chain loops back on itself
SYNOPSIS
========
```raku
use X::Selkie::WidgetCycle;
CATCH {
when X::Selkie::WidgetCycle {
note "widget tree is cyclic: {.chain}";
}
}
```
DESCRIPTION
===========
A Selkie widget tree is a tree by convention, not by construction: `parent` is a writable attribute that layout containers set when they adopt a child. One mis-ordered reparent — a container adopting a widget that is already one of its own ancestors — makes the "tree" cyclic, and every walk up a parent chain then runs forever.
Selkie's parent-chain walks all hop through `Selkie::Tree`'s `next-ancestor`, which throws this exception once a single walk exceeds `PARENT-CHAIN-LIMIT` hops. Catching it is rarely useful: it is always an upstream bug in whatever set `parent`, and the whole point of throwing is that the alternative — a render thread spinning on an endless chain, with a frozen screen and no keyboard — is undiagnosable from the outside.
`chain` holds a bounded, human-readable rendering of the widgets involved (class name and `widget-id`, joined by arrows), which is normally enough to identify the offending container directly. `hops` is the budget that was exceeded.
SEE ALSO
========
* [Selkie::Tree](Selkie--Tree.md) — `next-ancestor`, `PARENT-CHAIN-LIMIT`, and the walk contract
* [Selkie::Widget](Selkie--Widget.md) — where `parent` lives
class X::Selkie::WidgetCycle
----------------------------
Thrown when a parent-chain walk exceeds Selkie::Tree's `PARENT-CHAIN-LIMIT`, i.e. when the widget tree contains a cycle.
### has Str $.chain
Bounded description of the widgets on the offending chain, as `Class#id -` Class#id -> …>.
### has Int $.hops
The hop budget that was exceeded.