Validation Rules

The Storybook compiler performs multi-layered validation to catch errors before runtime. This chapter documents all validation rules, organized by declaration type, along with the error messages you can expect and how to fix them.

Validation Layers

Storybook validation happens in four stages:

  1. Lexical: Tokenization of raw text (invalid characters, malformed literals)
  2. Syntactic: Grammar structure (missing braces, wrong keyword order)
  3. Semantic: Cross-reference resolution, type checking, field merging
  4. Domain: Narrative-specific constraints (bond ranges, schedule overlaps)

Errors at earlier stages prevent later stages from running.

Character Validation

Required Rules

RuleDescriptionSeverity
Unique nameCharacter names must be unique within their moduleError
Species existsIf : Species is used, the species must be definedError
Templates existAll templates in from clause must be definedError
No circular inheritanceTemplate chains cannot form cyclesError
Field type consistencyField values must match expected typesError
Behavior trees existAll uses behaviors references must resolveError
Schedules existAll uses schedule references must resolveError
Prose tag uniquenessEach prose tag can appear at most once per characterError

Examples

Species not found:

character Martha: Hobbit {  // Error: species 'Hobbit' not defined
    age: 34
}

Fix: Define the species or correct the reference:

species Hobbit {
    lifespan: 130
}

character Martha: Hobbit {
    age: 34
}

Duplicate character name:

character Martha { age: 34 }
character Martha { age: 36 }  // Error: duplicate character name 'Martha'

Template Validation

RuleDescriptionSeverity
Unique nameTemplate names must be unique within their moduleError
Includes existAll included templates must be definedError
No circular includesInclude chains cannot form cyclesError
Range validityRange bounds must satisfy min <= maxError
Range type matchBoth bounds of a range must be the same typeError
Strict enforcementCharacters using strict templates cannot add extra fieldsError
Resource links validBehavior/schedule references must resolveError

Examples

Invalid range:

template BadRange {
    age: 65..18  // Error: range min (65) must be <= max (18)
}

Strict template violation:

template Rigid strict {
    required_stat: 10
}

character Constrained from Rigid {
    required_stat: 15
    extra_field: 42    // Error: field 'extra_field' not allowed by strict template 'Rigid'
}

Behavior Tree Validation

RuleDescriptionSeverity
At least one nodeBehavior body must contain at least one nodeError
Composite childrenchoose and then require at least one childError
Decorator childDecorators require exactly one childError
Subtree existsinclude must reference a defined behaviorError
Expression validityCondition expressions must be well-formedError
Duration formatDecorator durations must be valid (e.g., 5s, 10m)Error
Repeat count validrepeat N requires N >= 0Error
Repeat range validrepeat min..max requires 0 <= min <= maxError
Retry count validretry N requires N >= 1Error

Examples

Empty composite:

behavior Empty {
    choose options {
        // Error: 'choose' requires at least one child
    }
}

Invalid subtree reference:

behavior Main {
    include NonExistentBehavior  // Error: behavior 'NonExistentBehavior' not defined
}

Life Arc Validation

RuleDescriptionSeverity
At least one stateLife arc must contain at least one stateError
Unique state namesState names must be unique within the life arcError
Valid transitionsTransition targets must reference defined statesError
Expression validityTransition conditions must be well-formedError
Field targets validOn-enter field references must resolveError
Reachable statesAll states should be reachable from initial stateWarning

Examples

Invalid transition target:

life_arc Broken {
    state active {
        on timer_expired -> nonexistent  // Error: state 'nonexistent' not defined
    }
}

Unreachable state (warning):

life_arc HasOrphan {
    state start {
        on ready -> middle
    }

    state middle {
        on done -> end
    }

    state orphan {}  // Warning: state 'orphan' is not reachable

    state end {}
}

Schedule Validation

RuleDescriptionSeverity
Time formatTimes must be valid HH:MM or HH:MM:SSError
Extends existsBase schedule must be definedError
No circular extendsSchedule chains cannot form cyclesError
Named blocks uniqueBlock names must be unique within a scheduleError
Action references validAction references must resolve to defined behaviorsError
Constraint values validTemporal constraint values must reference defined enumsError
Recurrence names uniqueRecurrence names must be unique within a scheduleError

Examples

Invalid time format:

schedule Bad {
    block work {
        25:00 - 17:00  // Error: invalid hour '25'
        action: work
    }
}

Circular extends:

schedule A extends B { }
schedule B extends A { }  // Error: circular schedule extension detected

Relationship Validation

RuleDescriptionSeverity
At least two participantsRelationships require >= 2 participantsError
Participants existAll participant names must reference defined entitiesError
Unique participantsEach participant appears at most onceError
Field type consistencyFields must have valid value typesError

Examples

Too few participants:

relationship Lonely {
    Martha  // Error: relationship requires at least 2 participants
    bond: 0.5
}

Species Validation

RuleDescriptionSeverity
Unique nameSpecies names must be unique within their moduleError
No circular includesInclude chains cannot form cyclesError
Includes existAll included species must be definedError
Field type consistencyFields must have valid valuesError
Prose tag uniquenessEach prose tag can appear at most onceError

Enum Validation

RuleDescriptionSeverity
Unique enum nameEnum names must be unique within their moduleError
Unique variantsVariant names must be unique within the enumError
Non-emptyEnums must have at least one variantError
Valid identifiersVariants must follow identifier rulesError

Examples

Duplicate variant:

enum Size {
    tiny,
    small,
    small,  // Error: duplicate variant 'small' in enum 'Size'
    large
}

Institution and Location Validation

RuleDescriptionSeverity
Unique nameNames must be unique within their moduleError
Resource links validBehavior/schedule references must resolveError
Field type consistencyFields must have valid valuesError

Expression Validation

Expressions are validated wherever they appear (life arc transitions, behavior tree conditions, if decorators).

RuleDescriptionSeverity
Type consistencyBoth sides of comparison must have compatible typesError
Boolean contextLogical operators require boolean operandsError
Field existenceReferenced fields must exist on the entityError
Collection validityQuantifiers require collection-typed expressionsError
Variable scopeQuantifier variables only valid within their predicateError
Enum validityEnum comparisons must reference defined valuesError

Examples

Type mismatch:

life_arc TypeError {
    state checking {
        on count == "five" -> done  // Error: cannot compare int with string
    }

    state done {}
}

Use Statement Validation

RuleDescriptionSeverity
Path existsImported paths must reference defined modules/itemsError
No circular importsModules cannot form circular dependency chainsError
Valid identifiersAll path segments must be valid identifiersError
Grouped import validityAll items in {} must exist in the target moduleError

Examples

Missing import:

use schema::nonexistent::Thing;  // Error: module 'schema::nonexistent' not found

Cross-File Validation

When resolving across multiple .sb files, the compiler performs additional checks:

RuleDescriptionSeverity
All references resolveCross-file references must find their targetsError
No naming conflictsDeclarations must not collide across files in the same moduleError
Import visibilityOnly public declarations can be importedError

Common Error Patterns

Missing Definitions

The most common error is referencing something that does not exist:

character Martha: Human from Baker {
    specialty: sourdough
}

If Human, Baker, or the sourdough enum variant are not defined or imported, the compiler will report an error. Fix by adding the appropriate use statements:

use schema::core_enums::{SkillLevel, Specialty};
use schema::templates::Baker;
use schema::beings::Human;

character Martha: Human from Baker {
    specialty: sourdough
}

Circular Dependencies

Circular references are rejected at every level:

  • Templates including each other
  • Species including each other
  • Schedules extending each other
  • Modules importing each other

Break cycles by restructuring into a hierarchy or extracting shared parts into a common module.

Type Mismatches

Storybook has no implicit type coercion. Ensure values match their expected types:

// Wrong:
character Bad {
    age: "twenty"  // Error: expected int, got string
    is_ready: 1    // Error: expected bool, got int
}

// Correct:
character Good {
    age: 20
    is_ready: true
}

Validation Summary

DeclarationKey Constraints
CharacterUnique name, valid species/templates, no circular inheritance
TemplateUnique name, valid includes, valid ranges, strict enforcement
BehaviorNon-empty, valid composites, valid decorators, valid subtrees
Life ArcNon-empty, unique states, valid transitions, reachable states
ScheduleValid times, valid extends chain, unique block names
Relationship>= 2 participants, valid references
SpeciesUnique name, valid includes, no cycles
EnumUnique name, unique variants, non-empty
InstitutionUnique name, valid resource links
LocationUnique name, valid field types
UseValid paths, no circular imports

Cross-References