toeverything/AFFiNE · critical · BlockSuiteError
NoSurfaceModelError
NoSurfaceModelError
Error message
This doc is missing surface block in edgeless.
What it means
Thrown in the EdgelessRootBlockService constructor when getSurfaceBlock(this.doc) returns null — i.e. the doc has no surface block, which edgeless mode requires to hold vector/gfx primitive elements. Error code NoSurfaceModelError (a fatal-tier code > 10000). Construction of the service aborts, so the edgeless root block cannot initialise.
Source
Thrown at blocksuite/affine/blocks/root/src/edgeless/edgeless-root-service.ts:119
}
get viewport() {
return this.std.get(GfxControllerIdentifier).viewport;
}
get zoom() {
return this.viewport.zoom;
}
get crud() {
return this.std.get(EdgelessCRUDIdentifier);
}
constructor(std: BlockStdScope, flavourProvider: { flavour: string }) {
super(std, flavourProvider);
const surface = getSurfaceBlock(this.doc);
if (!surface) {
throw new BlockSuiteError(
ErrorCode.NoSurfaceModelError,
'This doc is missing surface block in edgeless.'
);
}
this._surface = surface;
}
private _initReadonlyListener() {
const doc = this.doc;
const slots = this.std.get(EdgelessLegacySlotIdentifier);
let readonly = doc.readonly;
this.disposables.add(
effect(() => {
if (readonly !== doc.readonly) {
readonly = doc.readonly;
slots.readonlyUpdated.next(readonly);View on GitHub (pinned to 26c515e050)
Solutions
- Before entering edgeless mode, ensure the doc has a surface block: if !doc.root || !getSurfaceBlock(doc), add 'affine:surface' to the root before mounting the edgeless root block.
- If building a doc programmatically, always add a surface block alongside the page root when edgeless is supported.
- Run a repair migration over older docs to insert a missing surface block.
Example fix
// before
// doc has no surface block -> EdgelessRootBlockService constructor throws
// after
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
if (!getSurfaceBlock(doc)) {
doc.addBlock('affine:surface', {}, doc.root!.id);
}
// now safe to initialise edgeless root service Defensive patterns
Strategy: validation
Validate before calling
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
function ensureSurface(doc) {
if (!getSurfaceBlock(doc)) {
doc.captureSync();
doc.addBlock('affine:surface', {}, doc.root.id);
}
} Type guard
import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
function hasSurfaceBlock(doc): boolean {
return !!getSurfaceBlock(doc);
} Prevention
- Always create a surface block when constructing a doc that will use edgeless mode.
- Run a repair migration that inserts a surface block into older page-only docs.
- Never delete the surface block of a doc that may be opened in edgeless mode.
When it happens
Trigger: Mounting/initialising an edgeless root block on a doc that has no surface block. Happens when a doc was created as a page-only doc (no surface added), when the surface block was deleted, or when a custom doc-construction pipeline skipped adding 'affine:surface'.
Common situations: Opening a page-mode doc in edgeless mode without first ensuring a surface block; corrupted/incomplete docs; custom doc factories that omit the surface block; migrations that drop the surface block.
Related errors
- GfxBlockElementError
- Unable to export content to canvas
- EdgelessExportError
- MissingViewModelError
- ValueNotExists
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/839f76740884faba.
Report an issue: GitHub.