{"record":{"id":"930f74b8a94fd28b","repo":"toeverything/AFFiNE","slug":"props-is-only-supported-in-flat-data-model","errorCode":null,"errorMessage":"props is only supported in flat data model","messagePattern":"props is only supported in flat data model","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"blocksuite/framework/store/src/model/block/block-model.ts","lineNumber":83,"sourceCode":"  stash!: (prop: keyof Props & string) => void;\n\n  get text(): Text | undefined {\n    return (this.props as { text?: Text }).text;\n  }\n\n  set text(text: Text) {\n    if (this.keys.includes('text')) {\n      (this.props as { text?: Text }).text = text;\n    }\n  }\n\n  yBlock!: YBlock;\n\n  _props!: SignaledProps<Props>;\n\n  get props() {\n    if (!this._props) {\n      throw new Error('props is only supported in flat data model');\n    }\n    return this._props;\n  }\n\n  get flavour(): string {\n    return this.schema.model.flavour;\n  }\n\n  get version() {\n    return this.schema.version;\n  }\n\n  get children() {\n    return this._childModels.value;\n  }\n\n  get store() {\n    return this._store;","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/blocksuite/framework/store/src/model/block/block-model.ts#L65-L101","documentation":"BlockModel.props returns the reactive proxy stored in _props, but only FlatSyncController ever assigns _props — it is used when a block's schema declares isFlatData: true (block.ts:54). In the default tree data model, SyncController copies props directly onto the model instance and leaves _props undefined, so this getter throws to signal that the proxy API does not exist for this block.","triggerScenarios":"Reading model.props (or assigning model.text = new Text(...), whose setter writes through this.props) on any block whose schema does not set isFlatData: true — e.g. doc.getBlockById(id).props.title on a standard affine:paragraph block.","commonSituations":"Copying a snippet written for flat-data-model blocks into code that runs against tree-model blocks; upgrading BlockSuite versions where a block family changed data model; generic utility code that assumes every model exposes a props proxy.","solutions":["Access props as plain fields on the model instead (model.title, model.text) — tree-model blocks expose props directly on the instance","If you own the block schema and need proxy-based access, define it with isFlatData: true and re-create existing blocks","In shared code, branch on whether the flat proxy exists (check the private _props or model.keys) before touching model.props"],"exampleFix":"// before\nconst title = model.props.title; // throws: props is only supported in flat data model\n\n// after — tree data model exposes props directly on the model\nconst title = model.title;\n\n// or, if you own the schema and want the flat proxy:\nconst MyBlock = defineBlockSchema({\n  flavour: 'my:block',\n  isFlatData: true,\n  props: () => ({ title: '' as string }),\n});","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function hasFlatProps(model: BlockModel): boolean {\n  return (model as unknown as { _props?: unknown })._props !== undefined;\n}","tryCatchPattern":null,"preventionTips":["Never read model.props on blocks you did not define with isFlatData: true","Prefer typed field access (model.text, model.title) which works in both data models","Guard shared utilities with hasFlatProps(model) before touching the proxy"],"tags":["blocksuite","block-model","flat-data-model","props","api-misuse"],"backgroundTag":"invalid-state-access","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}