Skip to content
HomePagesHomePages template kit
Menu

template-kit/schema-invalid

The template-kit/schema-invalid authoring rule — what it enforces, why, and how to fix it.

schema.ts and fill-spec.ts are a matched pair. This is every check that makes sure they actually agree.

A section’s schema.ts and fill-spec.ts must, together:

  • parse — each is as const satisfies its shape (SectionSchemaShape, FillSpecShape); a value that doesn’t satisfy it fails here with the parse error;
  • cross-reference correctly — every fill-spec.ts decision produces a slot that actually exists in schema.ts, every reads entry names a real, author-declarable facts key, every option’s affects_decisions/affects_slots names a real decision or slot;
  • satisfy the closed per-type contracts — an object_list slot’s item_order covers every field, a select slot’s cases match its transform, a group’s members are slots that exist, and the rest of the per-slot-type rules the schema system documents.

One violation is one diagnostic; a section with several wrong things reports all of them in the same run, not one per fix.

This is the id you also see when a section cannot be built or parsed at all — a syntax error in schema.ts, a missing export, an import that doesn’t resolve. The message in that case is the underlying build error, relocated to the file it points at.

fill-spec.ts is not free-standing — every decision it declares exists to fill a slot schema.ts declared, and every fact it reads must be one the platform actually exposes. A decision that produces a slot no schema declares, or reads a fact that doesn’t exist, is not a style problem: the fill pipeline would either drop the output on the floor or crash trying to read a fact key that isn’t there. Catching the mismatch here, at author time, is the difference between a red check and a listing that silently fails to fill.

Read the message: it names the section, the decision or slot in question, and what’s wrong with it. Fix whichever side is actually stale — the schema, or the fill-spec.

sections/facts/schema.ts
export const schema = {
meta: { displayName: "Facts" },
slots: {
year_built: { type: "text", required: false, produced_by: "year_built_text" },
},
options: {},
} as const satisfies SectionSchemaShape;
sections/facts/fill-spec.ts
export const fillSpec = {
reads: [],
decisions: [
{ id: "year_built_text", type: "text-block", produces: ["year_built_summary"], length_cap: 20 },
// ^ typo — schema.ts declares "year_built"
],
} as const satisfies FillSpecShape;
Section "facts": fill-spec decision "year_built_text" produces unknown slot "year_built_summary".
sections/facts/fill-spec.ts
export const fillSpec = {
reads: [],
decisions: [
{ id: "year_built_text", type: "text-block", produces: ["year_built"], length_cap: 20 },
],
} as const satisfies FillSpecShape;
  • The schema system — the full authoring contract for schema.ts and fill-spec.ts.
  • fixtures-invalid — the sibling gate on the third contract file, fixtures.ts.
  • manifest-invalid — the same kind of cross-reference check, one level up, on a template composing several sections.
  • bundle-incomplete — reported instead of this id when a contract file is missing outright, rather than present and wrong.