toeverything/AFFiNE · error · BlockSuiteError
EdgelessExportError
EdgelessExportError
Error message
Could not find edgeless block component.
What it means
FrameworkStackProvider layers several providers and resolves each identifier against the first provider in the stack that has it. An empty stack would make every lookup fail with nothing to attribute the failure to, so the constructor rejects an empty providers array immediately rather than producing a permanently broken provider.
Solutions
- Ensure at least one FrameworkProvider is passed — typically the base app framework first, then optional plugin frameworks
- Guard before construction: if the dynamic list is empty, fall back to the plain base provider
- Fix the upstream filter/map that emptied the list (feature flag disabling every provider, wrong predicate)
Example fix
// before const providers = enabledPlugins.map(p => p.provider); // [] when all disabled const stack = new FrameworkStackProvider(providers); // throws // after const providers = [baseProvider, ...enabledPlugins.map(p => p.provider)]; const stack = new FrameworkStackProvider(providers);
Defensive patterns
Strategy: validation
Validate before calling
function createStackProvider(
base: FrameworkProvider,
extras: FrameworkProvider[]
): FrameworkProvider {
const providers = [base, ...extras].filter(Boolean);
if (providers.length === 0) {
throw new Error('No providers available: at least the base framework is required');
}
return providers.length === 1 ? providers[0] : new FrameworkStackProvider(providers);
} Type guard
null
Prevention
- Always put the base app provider first when composing a stack from optional plugin providers
- Validate dynamically built provider lists for non-emptiness before constructing FrameworkStackProvider
- Check feature-flag combinations that can filter every provider out
When it happens
Trigger: new FrameworkStackProvider(providers) where providers was built dynamically (map/filter) and ended up empty; passing [] via a default parameter when a feature flag filtered out every framework; constructing the stack before the list of plugin providers is populated.
Common situations: Composing optional plugins where zero are enabled in a minimal build; conditional test setups that skip all providers; refactor moving stack construction above the code that fills the list.
Related errors
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/ee49801bf11f281b.
Report an issue: GitHub.
Appendix: 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 b4c8548c09)