{"record":{"id":"d4e630593996c609","repo":"toeverything/AFFiNE","slug":"errorcode-modelcruderror-d4e630","errorCode":"ErrorCode.ModelCRUDError","errorMessage":"schema for flavour: ${this.flavour} not found","messagePattern":"schema for flavour: (.+?) not found","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"error","filePath":"blocksuite/framework/store/src/model/block/sync-controller.ts","lineNumber":133,"sourceCode":"    readonly onChange?: (key: string, isLocal: boolean) => void\n  ) {\n    const { id, flavour, version, yChildren, props } = this._parseYBlock();\n\n    this.id = id;\n    this.flavour = flavour;\n    this.yChildren = yChildren;\n    this.version = version;\n\n    this.model = this._createModel(props);\n\n    this._observeYBlockChanges();\n  }\n\n  private _createModel(props: UnRecord) {\n    const _mutex = this._mutex;\n    const schema = this.schema.flavourSchemaMap.get(this.flavour);\n    if (!schema) {\n      throw new BlockSuiteError(\n        ErrorCode.ModelCRUDError,\n        `schema for flavour: ${this.flavour} not found`\n      );\n    }\n\n    const model = schema.model.toModel?.() ?? new BlockModel<object>();\n    model.schema = schema;\n    const signalWithProps = Object.entries(props).reduce(\n      (acc, [key, value]) => {\n        const data = signal(value);\n        const dispose = effect(() => {\n          const value = data.value;\n          if (!this.model) return;\n          _mutex(() => {\n            // @ts-expect-error allow magic props\n            this.model.props[key] = value;\n          });\n        });","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/blocksuite/framework/store/src/model/block/sync-controller.ts#L115-L151","documentation":"Thrown by SyncController._createModel: the non-flat (classic) sync controller resolved this.flavour from the yBlock but schema.flavourSchemaMap.get(this.flavour) is undefined. Identical root cause to the flat variant (error 81) but reached through the standard SyncController path used for non-flat-data blocks.","triggerScenarios":"Instantiating a SyncController for a block whose 'sys:flavour' is not present in the Schema registry; common when the schema is built per-doc but the flavour list is incomplete, or a block package failed to load.","commonSituations":"Forgot to pass a block schema to the Doc collection's schema; dynamic import race where the doc renders before the block module finishes registering; flavour string typo or casing mismatch between data and registration; peer-supplied doc referencing an unavailable block.","solutions":["Register the missing flavour in the Schema before the SyncController is constructed.","Verify the flavour string in 'sys:flavour' matches exactly (case-sensitive) the flavour in the block's schema definition.","Add a migration/alias if the flavour was renamed.","Build a startup assertion that walks the doc's flavours and fails fast with a readable list of unregistered flavours."],"exampleFix":"// before\nconst schema = new Schema();\n// forgot list block\nconst store = new Store({ schema, id });\n\n// after\nconst schema = new Schema();\nschema.register([ParagraphSchema, ListSchema, ...]);\nconst store = new Store({ schema, id });","handlingStrategy":"validation","validationCode":"export function ensureFlavour(schema: Schema, flavour: string): void {\n  if (!schema.flavourSchemaMap.has(flavour)) {\n    throw new Error(`SyncController: flavour '${flavour}' missing from schema. Registered: ${[...schema.flavourSchemaMap.keys()].join(', ')}`);\n  }\n}\n\nensureFlavour(schema, yBlock.get('sys:flavour') as string);\nnew SyncController(schema, yBlock, doc, onChange);","typeGuard":"export const hasSchemaForFlavour = (schema: Schema, flavour: string): boolean =>\n  schema.flavourSchemaMap.has(flavour);","tryCatchPattern":"try {\n  new SyncController(schema, yBlock, doc, onChange);\n} catch (e) {\n  if (e instanceof BlockSuiteError && e.code === ErrorCode.ModelCRUDError && /schema for flavour/.test(e.message)) {\n    await loadBlockPackageFor(extractFlavour(e.message));\n    // retry once registration settles\n  } else throw e;\n}","preventionTips":["Register all block schemas before any doc opens.","Verify flavour strings match the schema definition exactly (case-sensitive).","Add a schema-coverage check at startup listing unregistered flavours found in the doc.","Avoid lazy registration that races with doc open."],"tags":["model-crud","schema","flavour-registration","sync-controller"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}