toeverything/AFFiNE · error · BlockSuiteError
MissingViewModelError
MissingViewModelError
Error message
can not find element(id:${referenceElement}) What it means
Thrown by the surface-ref block's SurfaceRefViewportWatcher.mounted() when crud.getElementById(referenceId) returns null — i.e. the edgeless element referenced by the surface-ref block (a frame or a primitive) cannot be found in the current doc/surface. Error code MissingViewModelError. The block stores a reference id; on mount it tries to resolve that element to subscribe to its viewport/position changes.
Source
Thrown at blocksuite/affine/blocks/surface-ref/src/surface-ref-block.ts:308
};
this.disposables.add(effect(refreshViewport));
const referenceId = this.model.props.reference;
const referenceXYWH$ = this._referenceXYWH$;
class SurfaceRefViewportWatcher extends LifeCycleWatcher {
static override readonly key = 'surface-ref-viewport-watcher';
private readonly _disposable = new DisposableGroup();
override mounted() {
const crud = this.std.get(EdgelessCRUDIdentifier);
const gfx = this.std.get(GfxControllerIdentifier);
const { surface, viewport } = gfx;
if (!surface) return;
const referenceElement = crud.getElementById(referenceId);
if (!referenceElement) {
throw new BlockSuiteError(
ErrorCode.MissingViewModelError,
`can not find element(id:${referenceElement})`
);
}
referenceXYWH$.value = referenceElement.xywh;
const { _disposable } = this;
refreshViewport();
_disposable.add(viewport.sizeUpdated.subscribe(refreshViewport));
if (referenceElement instanceof GfxBlockElementModel) {
_disposable.add(
referenceElement.xywh$.subscribe(xywh => {
referenceXYWH$.value = xywh;
})
);
} else if (referenceElement instanceof GfxPrimitiveElementModel) {
_disposable.add(View on GitHub (pinned to 26c515e050)
Solutions
- Before mounting/creating a surface-ref block, verify the referenced element exists via crud.getElementById(referenceId); if not, show a placeholder or remove the block.
- When deleting edgeless elements, also clean up or mark surface-ref blocks that reference them.
- If the element may load asynchronously, defer the throw: return early from mounted() when the element is missing instead of throwing (the watcher already returns early when !surface).
Example fix
// before
// referenced element deleted -> mounted() throws MissingViewModelError
// after (caller-side guard)
const ref = surfaceRefBlock.model.props.reference;
if (!crud.getElementById(ref)) {
// render a 'missing reference' placeholder instead
} else {
renderSurfaceRef(surfaceRefBlock);
} Defensive patterns
Strategy: validation
Validate before calling
const crud = std.get(EdgelessCRUDIdentifier);
if (!crud.getElementById(referenceId)) {
// render placeholder instead of mounting the surface-ref block
} Type guard
function referenceExists(crud, id) {
return !!crud.getElementById(id);
} Prevention
- Verify the referenced element exists before mounting a surface-ref block.
- When deleting edgeless elements, clean up surface-ref blocks that reference them.
- Treat a missing reference as a render-time placeholder, not a throw.
When it happens
Trigger: Rendering a surface-ref block whose model.props.reference points to an element id that does not exist: the referenced frame/shape was deleted, belongs to a different doc, or the surface is not loaded yet at mount time.
Common situations: Opening a doc where the referenced edgeless element was removed; cross-doc copy of a surface-ref block without its target; rendering the block before the surface/CRUD is ready; stale references after a migration that changed element ids.
Related errors
- GfxBlockElementError
- Unable to export content to canvas
- EdgelessExportError
- NoSurfaceModelError
- ValueNotExists
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/7b9f0aeae1bcc671.
Report an issue: GitHub.