Skip to content

symfonic.capabilities.delegation.errors

errors

The delegation error taxonomy, split by who is wrong.

Four kinds, and the split is not cosmetic. A declaration error means the deployment described a child that cannot exist and no input will fix it. A lockdown error means a child was handed over holding a surface a delegated child may never hold — also a deployment fact, but a security one, and the message has to say what to do instead. A duplicate is a wiring mistake in the roster, caught before anything is built. An unknown child is the only one of the four that can be produced by a running model, which is why the tool layer turns it into a message rather than letting it escape.

Nothing here is raised at delegation time on a healthy deployment. The tool surface's refusals — depth reached, child failed — are values, not exceptions: see :class:~.values.DelegationOutcome.

ChildDeclarationError

Bases: DelegationError, ValueError

A declared child is not describable: no name, no description, no runner.

Also a :class:ValueError because that is what the shipped declaration types raised, and an adopter's except ValueError around agent construction is a reasonable thing to have written.

ChildLockdownError

Bases: DelegationError, ValueError

A child would have held a prompt-block write surface.

A prompt block has exactly one writer. A delegated child that can write one is a second writer, and one the parent never sees — the child runs its own loop with its own palette. Raised at construction or registration, never mid-run: by the time a run starts, the palette has already been advertised.

DelegationError

Bases: Exception

Base for everything this capability raises.

DuplicateChildError

Bases: ChildDeclarationError

Two children claim the same routing key.

Raised before any child is constructed. A roster that answers one name with two children has no defensible resolution order, and picking one silently would route a task to a child the operator never chose.

UnknownChildError

Bases: DelegationError, KeyError

Nothing is registered under that routing key.

Raised by the roster, which has no opinion about how a caller should react. The tool surface catches it and answers the model with the roster instead, because a model that guessed a name needs the list, not a stack trace.

UnsanitisableChildConfigError

Bases: ChildLockdownError, TypeError

A config asked for the write surface and cannot be copied to clear it.

Also a :class:TypeError so the shipped behaviour of the engine's deny_child_self_edit — which raised exactly that — survives the move. A lock that gives up quietly on an input shape it did not expect is not a lock, so this is a refusal rather than a pass-through.