{"record":{"id":"84348b057f31d0f0","repo":"toeverything/AFFiNE","slug":"edgelessexporterror-84348b","errorCode":"EdgelessExportError","errorMessage":"Unable to export content to canvas","messagePattern":"Unable to export content to canvas","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"warning","filePath":"blocksuite/affine/blocks/surface/src/extensions/export-manager/export-manager.ts","lineNumber":112,"sourceCode":"    await Promise.all(promises);\n  };\n\n  get doc(): Store {\n    return this.std.store;\n  }\n\n  get editorHost(): EditorHost {\n    return this.std.host;\n  }\n\n  constructor(readonly std: BlockStdScope) {}\n\n  private _checkCanContinueToCanvas(pathName: string, editorMode: boolean) {\n    if (\n      location.pathname !== pathName ||\n      isInsidePageEditor(this.editorHost) !== editorMode\n    ) {\n      throw new BlockSuiteError(\n        ErrorCode.EdgelessExportError,\n        'Unable to export content to canvas'\n      );\n    }\n  }\n\n  private async _checkReady() {\n    const pathname = location.pathname;\n    const editorMode = isInsidePageEditor(this.editorHost);\n\n    const promise = new Promise((resolve, reject) => {\n      let count = 0;\n      const checkReactRender = setInterval(() => {\n        try {\n          this._checkCanContinueToCanvas(pathname, editorMode);\n        } catch (e) {\n          clearInterval(checkReactRender);\n          reject(e);","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/blocksuite/affine/blocks/surface/src/extensions/export-manager/export-manager.ts#L94-L130","documentation":"Thrown by ExportManager._checkCanContinueToCanvas (the surface block's export manager) under the same conditions as the clipboard variant [11]: location.pathname changed or isInsidePageEditor(editorHost) flipped between the start of the export and a continuation check. Error code EdgelessExportError (a structured BlockSuiteError, unlike [11]'s plain Error). It is polled inside _checkReady's interval and rejects the readiness promise on change.","triggerScenarios":"Calling ExportManager.docToCanvas/edgelessToCanvas and navigating to a different route or toggling page/edgeless mode while the readiness interval (10s window, 100ms ticks) or the html2canvas pipeline is still running. Also triggered if the SPA route changes for any reason mid-export.","commonSituations":"Long exports on heavy docs where the user navigates away; automated exports run concurrently with other code that mutates the route; browser back/forward during export; mode-toggle shortcuts pressed during export.","solutions":["Await the export promise and prevent route/mode changes until it resolves (disable the toggle, lock navigation).","Catch BlockSuiteError with code EdgelessExportError at the call site and treat it as cancellation, not a fatal fault.","Reduce export bound / pre-render off-screen blocks to shorten the window in which navigation can invalidate the export."],"exampleFix":"// before\nawait exportManager.edgelessToCanvas(bound); // throws if user navigates\n\n// after\nimport { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';\ntry {\n  await exportManager.edgelessToCanvas(bound);\n} catch (e) {\n  if (e instanceof BlockSuiteError && e.code === ErrorCode.EdgelessExportError) {\n    notify('Export cancelled: view changed.');\n  } else throw e;\n}","handlingStrategy":"try-catch","validationCode":"// prevent navigation/mode changes during export\nconst pathName = location.pathname;\nconst editorMode = isInsidePageEditor(editorHost);\nsetNavigationLocked(true);\nawait exportManager.edgelessToCanvas(bound);\nsetNavigationLocked(false);","typeGuard":null,"tryCatchPattern":"import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';\ntry { await exportManager.edgelessToCanvas(bound); }\ncatch (e) {\n  if (e instanceof BlockSuiteError && e.code === ErrorCode.EdgelessExportError) {\n    // cancellation: view changed mid-export\n  } else throw e;\n}","preventionTips":["Lock navigation and mode toggles while an export is in flight.","Await the export promise before releasing the lock.","Treat EdgelessExportError from the readiness check as cancellation."],"tags":["export","edgeless","navigation-guard","edgeless-export-error"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}