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

  1. 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.
  2. When deleting edgeless elements, also clean up or mark surface-ref blocks that reference them.
  3. 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

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


AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12). Data as JSON: /api/errors/7b9f0aeae1bcc671. Report an issue: GitHub.