toeverything/AFFiNE · error · BlockSuiteError
ErrorCode.ModelCRUDError
ErrorCode.ModelCRUDError
Error message
schema for flavour: ${this.flavour} not found What it means
Thrown by `FlatSyncController._createModel` when `schema.flavourSchemaMap.get(this.flavour)` returns undefined. The controller is constructing a `BlockModel` from a yjs block map; the block's flavour has no matching schema, meaning the flavour was never registered with the `Schema` passed to the store. Note `_parseYBlock` already throws the same message earlier if the schema is missing there too.
Source
Thrown at blocksuite/framework/store/src/model/block/flat-sync-controller.ts:43
readonly schema: Schema,
readonly yBlock: YBlock,
readonly doc?: Store,
readonly onChange?: (key: string, isLocal: boolean) => void
) {
const { id, flavour, version, yChildren, props } = this._parseYBlock();
this.id = id;
this.flavour = flavour;
this.yChildren = yChildren;
this.version = version;
this.model = this._createModel(props);
}
private _createModel(props: Set<string>) {
const schema = this.schema.flavourSchemaMap.get(this.flavour);
if (!schema) {
throw new BlockSuiteError(
ErrorCode.ModelCRUDError,
`schema for flavour: ${this.flavour} not found`
);
}
const model = schema.model.toModel?.() ?? new BlockModel<object>();
const defaultProps = schema.model.props?.(internalPrimitives);
model.schema = schema;
model.id = this.id;
model.keys = Array.from(props);
model.yBlock = this.yBlock;
const reactive = new ReactiveFlatYMap(
this.yBlock,
model.deleted,
this.onChange,
defaultProps
);View on GitHub (pinned to 26c515e050)
Solutions
- Register every flavour the doc may contain with the `Schema` before constructing the store / loading the doc.
- Gate doc load on flavour registration being complete (await the module that registers the schema).
- If you intentionally receive foreign flavours, filter them out of the yjs map before model creation, or register a stub schema.
Example fix
// before: store built with a partial schema
const schema = new Schema([PageBlockSchema]);
const store = createStore({ schema, id: 'doc' });
store.load(binaryContainingCustomBlock); // throws: schema for flavour not found
// after: register every flavour the doc may contain
const schema = new Schema([PageBlockSchema, CustomBlockSchema]);
const store = createStore({ schema, id: 'doc' });
store.load(binaryContainingCustomBlock); Defensive patterns
Strategy: validation
Validate before calling
// verify every flavour referenced by the doc is in the schema before loading
function allFlavoursRegistered(schema: Schema, flavours: string[]): boolean {
return flavours.every(f => schema.flavourSchemaMap.has(f));
}
const flavours = collectFlavoursFromYDoc(yDoc);
if (!allFlavoursRegistered(schema, flavours)) {
throw new Error('Register all block flavours before loading the doc');
} Type guard
function schemaHasFlavour(schema: Schema, flavour: string): boolean {
return schema.flavourSchemaMap.has(flavour);
} Try / catch
try {
store.load(binary);
} catch (e) {
if (e instanceof BlockSuiteError && e.code === ErrorCode.ModelCRUDError) {
console.error('Schema missing flavour:', e.message);
}
} Prevention
- Register every block flavour with the Schema before constructing the store.
- Gate doc load on flavour registration completing.
- Filter or stub foreign flavours if you intentionally receive them.
When it happens
Trigger: A yjs document contains a block whose `sys:flavour` is not in the schema — e.g. collaborative peer with a block flavour the local app does not register, a snapshot import of an unknown flavour, or the `Schema` was built without all the block `defineBlockSchema` calls.
Common situations: App build A registers `{affine:page}` and build B adds `{affine:custom}`; B's doc syncs to A and A throws. Forgetting to call `Schema` with all block flavours; lazy-loading a block flavour but the doc loads before the flavour registration completes.
Related errors
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/2f2cddc48e0d08eb.
Report an issue: GitHub.