toeverything/AFFiNE · error · BlockSuiteError
EdgelessExportError
EdgelessExportError
Error message
Could not find edgeless block component.
What it means
Thrown during edgeless-to-canvas export by _drawTopLevelBlock when std.view.getBlock(block.id) returns null/undefined for a block model being rendered to the canvas. html2canvas needs the live DOM component; if it is not mounted/registered in the view layer the export cannot proceed. Error code EdgelessExportError.
Source
Thrown at blocksuite/affine/blocks/root/src/edgeless/clipboard/clipboard.ts:507
boxShadowElements.forEach(function (element) {
if (element instanceof HTMLElement) {
element.style.setProperty('box-shadow', 'none');
}
});
await replaceImgSrcWithSvg?.(element);
},
backgroundColor: 'transparent',
useCORS: imageProxy ? false : true,
proxy: imageProxy,
};
const _drawTopLevelBlock = async (
block: GfxBlockElementModel,
isInFrame = false
) => {
const blockComponent = this.std.view.getBlock(block.id);
if (!blockComponent) {
throw new BlockSuiteError(
ErrorCode.EdgelessExportError,
'Could not find edgeless block component.'
);
}
const blockBound = Bound.deserialize(block.xywh);
const canvasData = await html2canvas(
blockComponent as HTMLElement,
html2canvasOption
);
ctx.drawImage(
canvasData,
blockBound.x - bound.x + padding,
blockBound.y - bound.y + padding,
blockBound.w,
isInFrame
? (blockBound.w / canvasData.width) * canvasData.height
: blockBound.hView on GitHub (pinned to 26c515e050)
Solutions
- Ensure all blocks in the export bound are mounted before exporting — scroll them into view or disable virtualisation during export.
- Confirm all referenced block flavours have their components registered with the editor host.
- Filter the node list passed to _edgelessToCanvas to blocks whose std.view.getBlock(id) is non-null, skipping unmounted ones.
Example fix
// before // export selection includes a not-yet-mounted block -> throws // after // wait one frame / use the readiness check before exporting await exportManager.docToCanvas(); // runs after _checkReady confirms mount
Defensive patterns
Strategy: validation
Validate before calling
const mounted = nodes.filter(b => !!std.view.getBlock(b.id)); // pass only mounted blocks to the export await edgelessToCanvas(bound, mounted, canvasElements, opts);
Type guard
function isBlockMounted(std, id) {
return !!std.view.getBlock(id);
} Try / catch
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
try { await edgelessToCanvas(...); }
catch (e) {
if (e instanceof BlockSuiteError && e.code === ErrorCode.EdgelessExportError) {
// retry after ensuring mount, or skip missing blocks
} else throw e;
} Prevention
- Ensure all blocks in the export bound are mounted (scroll into view / disable virtualisation) before exporting.
- Register all block flavour components with the host.
- Filter the node list to mounted components before exporting.
When it happens
Trigger: Exporting an edgeless canvas to an image while one of the blocks in the export bound has no rendered component — e.g. it is lazy-loaded/virtualised off-screen, was just deleted, belongs to an unregistered flavour, or the view layer has not yet mounted it.
Common situations: Virtualised/lazy-rendered blocks not yet in the DOM at export time; exporting immediately after adding blocks before React mounts them; exporting a selection that includes a block whose flavour component is not registered; race after block deletion where the model lingers but the component is gone.
Related errors
- EdgelessExportError
- Unable to export content to canvas
- GfxBlockElementError
- NoSurfaceModelError
- MissingViewModelError
AI-assisted analysis of toeverything/AFFiNE@26c515e050 (2026-08-12).
Data as JSON: /api/errors/ee49801bf11f281b.
Report an issue: GitHub.