-
Notifications
You must be signed in to change notification settings - Fork 0
Errors
The sentinels an extension branches on. They live in this module, not in
rex, because an extension depends on the contract and not on the framework —
a sentinel declared only in rex is unreachable from the code that needs to
match it.
Before these existed, extensions were reduced to
strings.Contains(err.Error(), "already exists"). That appeared in bothrextension-healthandrextension-metric, coupling each of them to the exact wording of another module's error string.
rex aliases all three, so errors.Is matches across either import path.
CreateRouter was called for a name already taken.
Usually not a failure. Two extensions may both want a router called
metrics, and whichever runs second should reuse it rather than abort startup.
The standard shape:
if err := r.CreateRouter(name, cfg); err != nil &&
!errors.Is(err, rextension.ErrRouterExists) {
return err
}Note that the first extension's configuration wins. If both pass a
RouterConfig, the second one's is discarded — which is the right default, but
worth a log line if your extension cares about its limits.
A route or middleware named a router that was never created.
Reported when the route table is built, not at the registration call, because whether a router exists depends on every extension having had its turn to create one. The error is wrapped with the method, path and call site of the registration that named it, so the source of a typo is in the message.
A route or middleware was registered after the route table was built.
The table is published by atomic swap and read without a lock, so there is
nowhere safe to add to it. Register from OnInitialize or OnStart — never
from OnReady.
If you hit this while upgrading, an OnReady hook is almost certainly the
cause; move the registration to OnStart.
These live in rex and are not aliased here, because extension code has no
occasion to match them:
rex.ErrAlreadyRunning |
a second call to Run
|
rex.ErrRouterNotFrozen |
a router was started before its table was built |
rex.ErrNilRoute |
a nil route, or one with no handler |
Resolution and registration failures come from
dix —
ErrNotRegistered, ErrScopedFromRoot, ErrAmbiguousResolution,
ErrAlreadyRegistered, ErrInvalidFactory, ErrInvalidTarget,
ErrScopeClosed.
An extension that wants to branch on one does have to import dix for the
sentinel. In practice most extension code does not: a failed resolve during
OnInitialize should abort startup, and a failed resolve in a handler should
answer with ProblemInternal. Neither needs to know which
failure it was.
rextension — the Rex extension contract · MIT · © 2026 Kryovyx · pre-1.0, interfaces may change
Building an extension
Contracts
Reference
Ecosystem