toeverything/AFFiNE · error · BlockSuiteError
ErrorCode.MissingViewModelError
ErrorCode.MissingViewModelError
Error message
Cannot find block model for id ${this.blockId} What it means
BlockComponent.model getter resolves the component's blockId through store.getModelById(); if the doc no longer contains a model with that id it throws MissingViewModelError instead of returning undefined. This happens when a view component outlives its model — the block was deleted from the yjs doc but the custom element is still mounted or being read.
Solutions
- Check existence before use: const model = doc.getModelById(component.blockId); if (!model) skip teardown logic.
- Do removals through the standard APIs (doc.deleteBlock) so views unmount with the model; let the view registry drive element lifetime.
- Never cache BlockComponent instances across mutations — re-query via std.view.getBlock(id).
- In custom components, avoid touching this.model after disconnectedCallback.
Example fix
// before const comp = std.view.getBlock(id); const flavour = comp.model.flavour; // throws if model deleted // after const comp = std.view.getBlock(id); const model = comp ? doc.getModelById(comp.blockId) : null; if (!model) return; const flavour = model.flavour;
Defensive patterns
Strategy: type-guard
Validate before calling
const model = doc.getModelById(component.blockId);
if (model) {
// safe to read component.model / render
} Type guard
function blockModelExists(doc: Store, blockId: string): boolean {
return doc.getModelById(blockId) != null;
} Prevention
- Delete blocks via doc.deleteBlock so views unmount with their models.
- Re-query components through std.view.getBlock(id) instead of caching element references.
- Never read this.model after disconnectedCallback or outside the render lifecycle.
When it happens
Trigger: Reading this.model (directly or via parentComponent/childComponent/render) on a BlockComponent whose blockId has no model in the store: block deleted while its element was still connected, a stale element retained after a view re-render, or a component created with a wrong/unset blockId.
Common situations: Deleting blocks programmatically while their components are mid-lifecycle; undo/redo replacing a model id; custom code holding references to block components past deletion; snapshot import that doesn't map ids consistently.
Related errors
- ErrorCode.ModelCRUDError
- ErrorCode.NoRootModelError
- ErrorCode.ValueNotExists
- ModelCRUDError
- props is only supported in flat data model
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/24a6f0233876db0d.
Report an issue: GitHub.
Appendix: source
Thrown at blocksuite/framework/std/src/view/element/block-component.ts:114
const expectedVersion = schema.version;
const actualVersion = this.model.version;
if (expectedVersion !== actualVersion) {
console.warn(
`Version mismatch for block ${this.model.id}, expected ${expectedVersion}, actual ${actualVersion}`
);
return true;
}
return false;
}
get model() {
if (this._model) {
return this._model;
}
const model = this.store.getModelById<Model>(this.blockId);
if (!model) {
throw new BlockSuiteError(
ErrorCode.MissingViewModelError,
`Cannot find block model for id ${this.blockId}`
);
}
this._model = model;
return model;
}
get parentComponent(): BlockComponent | null {
const parent = this.model.parent;
if (!parent) return null;
return this.std.view.getBlock(parent.id);
}
get renderChildren() {
return this.host.renderChildren.bind(this);
}
View on GitHub (pinned to b4c8548c09)