toeverything/AFFiNE · error · SchemaValidateError

SchemaValidateError

SchemaValidateError

Error message

Invalid schema for ${flavour}: Schema not found. The block flavour may not be registered.

What it means

Thrown by Schema.validate() when the primary block flavour being validated is not present in the flavourSchemaMap. BlockSuite maintains a registry of block schemas (flavours) and this error indicates the flavour string was never registered via Schema.register() before being used. The error surfaces during any structural validation that checks parent/child relationships for a block tree.

Source

Thrown at blocksuite/framework/store/src/schema/schema.ts:65

  }

  /**
   * Validates the schema relationship for a given flavour, parent, and children.
   * Throws SchemaValidateError if invalid.
   *
   * @param flavour - The block flavour to validate.
   * @param parentFlavour - The parent block flavour (optional).
   * @param childFlavours - The child block flavours (optional).
   * @throws {SchemaValidateError} If the schema relationship is invalid.
   */
  validate = (
    flavour: string,
    parentFlavour?: string,
    childFlavours?: string[]
  ): void => {
    const schema = this.flavourSchemaMap.get(flavour);
    if (!schema) {
      throw new SchemaValidateError(flavour, SCHEMA_NOT_FOUND_MESSAGE);
    }

    const validateChildren = () => {
      childFlavours?.forEach(childFlavour => {
        const childSchema = this.flavourSchemaMap.get(childFlavour);
        if (!childSchema) {
          throw new SchemaValidateError(childFlavour, SCHEMA_NOT_FOUND_MESSAGE);
        }
        this.validateSchema(childSchema, schema);
      });
    };

    if (schema.model.role === 'root') {
      if (parentFlavour) {
        throw new SchemaValidateError(
          schema.model.flavour,
          'Root block cannot have parent.'
        );

View on GitHub (pinned to 26c515e050)

Solutions

  1. Check that the flavour string exactly matches the flavour defined in the block's schema definition (including the namespace prefix like 'affine:').
  2. Ensure Schema.register([BlockSchema1, BlockSchema2, ...]) is called with all block schemas before any doc/store operations that reference them.
  3. Verify the block definition module (e.g. the file calling defineBlockSchema) is imported as a side-effect so the schema is available at runtime.
  4. Use schema.get(flavour) to check existence before calling validate, or use schema.safeValidate() which returns false instead of throwing.

Example fix

// before
const schema = new Schema();
// forgot to register
doc.addBlock('affine:paragraph', {}); // throws SchemaValidateError

// after
import { ParagraphBlockSchema } from './blocks/paragraph';
const schema = new Schema();
schema.register([ParagraphBlockSchema /* , ...other schemas */]);
doc.addBlock('affine:paragraph', {});
Defensive patterns

Strategy: validation

Validate before calling

if (!schema.get(flavour)) {
  throw new Error(`Flavour '${flavour}' is not registered. Register it via Schema.register([...]) first.`);
}
schema.validate(flavour, parentFlavour, childFlavours);

Type guard

const isRegisteredFlavour = (schema: Schema, flavour: string): boolean =>
  schema.flavourSchemaMap.has(flavour);

Try / catch

try {
  schema.validate(flavour, parentFlavour, childFlavours);
} catch (e) {
  if (e instanceof SchemaValidateError) {
    console.error(`Schema validation failed for ${flavour}: ${e.message}`);
    // handle: register missing schema or skip the block
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling schema.validate('affine:unknown', parentFlavour, childFlavours) where 'affine:unknown' was never registered. Also triggered indirectly by Store.addBlock() or any operation that constructs or mutates block trees when the flavour has not been registered on the Schema instance.

Common situations: Forgetting to call Schema.register([...]) with the full block schema array before creating a doc. Using a custom block flavour string that has a typo or mismatch with the registered flavour name. Dynamic plugin/extension loading where the block definition module was not imported before block creation. Version upgrades where a flavour was renamed or removed.

Related errors


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/23065aba3eea250c. Report an issue: GitHub.