toeverything/AFFiNE · error · BlockSuiteError
GfxBlockElementError
GfxBlockElementError
Error message
Frame model is not found
What it means
Thrown by FrameManager._addFrameBlock after gfx.doc.addBlock('affine:frame', ...) when gfx.getElementById(id) returns null or something that fails isFrameBlock. This means the freshly added block either was not committed/registered by the time of lookup, or the flavour/schema for 'affine:frame' is not registered so addBlock produced an unexpected model. Error code GfxBlockElementError.
Source
Thrown at blocksuite/affine/blocks/frame/src/frame-manager.ts:224
frame.addChildren(childElements);
}
private _addFrameBlock(bound: Bound) {
const surfaceModel = this.gfx.surface as SurfaceBlockModel;
const props = this.gfx.std
.get(EditPropsStore)
.applyLastProps('affine:frame', {
title: new Text(new Y.Text(`Frame ${this.frames.length + 1}`)),
xywh: bound.serialize(),
index: this.gfx.layer.generateIndex(true),
presentationIndex: this.generatePresentationIndex(),
});
const id = this.gfx.doc.addBlock('affine:frame', props, surfaceModel);
const frameModel = this.gfx.getElementById(id);
if (!frameModel || !isFrameBlock(frameModel)) {
throw new BlockSuiteError(
ErrorCode.GfxBlockElementError,
'Frame model is not found'
);
}
return frameModel;
}
private _watchElementAdded() {
if (!this.gfx.surface) {
return;
}
const { surface: surfaceModel, doc } = this.gfx;
this._disposable.add(
surfaceModel.elementAdded.subscribe(({ id, local }) => {
const element = surfaceModel.getElementById(id);View on GitHub (pinned to 26c515e050)
Solutions
- Ensure the 'affine:frame' block schema is registered (import the frame block module / add its extension) before the edgeless editor mounts.
- Ensure addBlock is called within a proper store context (doc.addBlock with a valid surfaceModel parent) and that the doc is not destroyed mid-call.
- If the race is timing-related, defer frame creation until the surface block is available (gfx.surface truthy) — _watchElementAdded already guards on surface presence.
Example fix
// before // affine:frame schema not registered -> getElementById returns null // after import '@blocksuite/affine-block-frame'; // registers the frame schema // then mount the editor; frame creation will resolve a FrameBlockModel
Defensive patterns
Strategy: validation
Validate before calling
import { isFrameBlock } from '@blocksuite/affine-block-frame';
function tryAddFrame(manager, bound) {
if (!manager.gfx.surface) return null; // surface not ready
return manager.addFrame(bound);
} Type guard
import { isFrameBlock } from '@blocksuite/affine-block-frame';
import type { GfxBlockElementModel } from '@blocksuite/affine-model';
function isFrame(model): model is FrameBlockModel {
return !!model && isFrameBlock(model);
} Prevention
- Register the affine:frame schema before mounting edgeless.
- Only add frames when gfx.surface is present and the doc is writable.
- Ensure addBlock runs inside a valid store transaction with a real surfaceModel parent.
When it happens
Trigger: Calling the public add-frame path (FrameManager.addFrame or whatever calls _addFrameBlock) before the affine:frame schema is registered, or when the surface model passed to addBlock is invalid/missing, or when an idGenerator/transaction timing issue causes getElementById to miss the just-added block.
Common situations: Initialising the edgeless surface before all block schemas are registered; calling frame creation during doc load before the surface block is ready; custom builds that tree-shake the frame block; race conditions where addBlock runs inside an uncommitted transaction.
Related errors
- Unable to export content to canvas
- EdgelessExportError
- NoSurfaceModelError
- MissingViewModelError
- ValueNotExists
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/a7ec11917cb7e295.
Report an issue: GitHub.