On this page
SpellbookValidationError๏
Use md.SpellbookValidationError from the public package namespace.
- class SpellbookValidationError(broken_spells: list[Spell], *, system_diagnostics: Sequence[SystemDiagnostic] | None = None, preface: str | None = None)[source]๏
Raised when the Spellbook pipeline finds spells it cannot build.
Conjure raises it after the structural phases (1-4) when a spell failed validation, and after the resolution phases when the conduit verdict holds an error; meld raises it when a spell's validity is invalid, gated or disabled after a lazy re-validation. No Conduit is constructed first.
- Purpose:
Tell a user which spells failed, why, and how to fix it, in plain words and by name, while keeping the spell objects for tooling.
Raised When:
conjure(...) completes phases 1-4 and one or more spells are broken. This is the common case: the pipeline ran, validation rejected the graph, and no Conduit is produced.
conjure(...) resolves the conduit and the verdict carries an error (for example a scope-ordering violation or a dependency cycle).
meld(...) finds a spell whose validity is invalid, gated, or disabled, including after a lazy re-validation attempt under the per-spell lock.
- What To Do About It:
Read the lines under each spell: every error names the parameter or the dependency at fault and says what to change. Errors marked [internal] come from Melder's own consistency checks and are Melder bugs; report them with the message. Warnings never block conjure and are only counted here, except one that holds a spell's SpellIndex gated (a lost SpellContract provider at meld): it is listed as that spell's reason, with its remedy. conjure(validation_warnings=True) logs the others. Fix the binding, not the validator.
Message shape (2026-09-26):
First line: "Spellbook validation failed. Broken spells: A, B." (the two substrings of earlier releases are kept for matchers).
One block per spell with errors, "Name (frame 'x'):", each error as " - <message> [CODE]"; errors that belong to no spell under "Whole-graph errors:".
Exact duplicates are dropped; BINDING_RESOLUTION_CYCLE is hidden when CIRCULAR_DEPENDENCY is reported for the same spell, and CIRCULAR_DEPENDENCY when SELF_DEPENDENCY is (a spell that depends on itself); root_not_viable and broken_spell_in_dag are hidden when any other error is shown.
A spell with no error that a Phase-4 warning holds gated (GATING_WARNING_CODES, a lost SpellContract provider) lists that warning as its reason, " - <message> [CODE]", instead of saying no error was recorded (D1-B, 2026-10-16).
Footers count the hidden warnings and explain [internal].
With preface (2026-10-19) that one line comes first and the message above follows it unchanged; a refused notch passes one, saying the notch did not happen (Spellbook._notch_spell, which Conduit.notch_spell calls inside its transaction).
Contract:
Always names the broken spells when spells are supplied.
Shows every recorded error reason: Phase 4 issues and Phase 6 errors on the spells, plus the conduit diagnostics handed in through system_diagnostics.
Never lists warnings, strategy sources or details payloads, except the gating warnings of a spell that shows no error: they are why its SpellIndex is gated, so they are its reason (2026-10-16).
Remains resilient when spell artifacts are partially unavailable or cleaned while the error is being rendered. Rendering a diagnostic must never raise a second error on top of the first.
The message is built once, at construction; the diagnostics handed in are read then and not retained.
- Registration:
Exported on the public root surface; import, raise, and catch freely.
- Subsystem Context:
One of the 11 utilities/custom_exceptions/ types and the primary error of the Spellbook binding surface. Where the scheduler family (PhaseExecutionError, PhaseTimeoutError) reports mechanical pipeline failure, this reports SEMANTIC failure: the phases ran fine and the graph they produced is not resolvable.
- System Context:
The main build-time error of the DGR. It fires before any Conduit is constructed, so nothing has been registered into Aether and there is no partial world to clean up. Its runtime counterpart is MeldExecutionError; between them they split "your graph cannot be built" from "your resolution failed while running".
AGENT_ACCESS: public
- AGENT_PURPOSE:
access: public. The build-time 'your graph is broken' error from conjure/meld; the message lists each broken spell's errors by name with a fix, plus whole-graph errors. Fix the binding, not the validator.