{"record":{"id":"b8799bfa46e660ed","repo":"toeverything/AFFiNE","slug":"valuenotexists-b8799b","errorCode":"ValueNotExists","errorMessage":"Failed to create portal root","messagePattern":"Failed to create portal root","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"error","filePath":"blocksuite/affine/components/src/portal/helper.ts","lineNumber":44,"sourceCode":"  identifyWrapper = true,\n}: PortalOptions) {\n  const portalRoot = document.createElement('div');\n  if (identifyWrapper) {\n    portalRoot.classList.add('blocksuite-portal');\n  }\n  if (shadowDom) {\n    portalRoot.attachShadow({\n      mode: 'open',\n      ...(typeof shadowDom !== 'boolean' ? shadowDom : {}),\n    });\n  }\n  signal.addEventListener('abort', () => {\n    portalRoot.remove();\n  });\n\n  const root = shadowDom ? portalRoot.shadowRoot : portalRoot;\n  if (!root) {\n    throw new BlockSuiteError(\n      BlockSuiteError.ErrorCode.ValueNotExists,\n      'Failed to create portal root'\n    );\n  }\n\n  let updateId = 0;\n  const updatePortal: (id: number) => void = id => {\n    if (id !== updateId) {\n      console.warn(\n        'Potentially infinite recursion! Please clean up the old event listeners before `updatePortal`'\n      );\n      return;\n    }\n    updateId++;\n    const curId = updateId;\n    const templateResult =\n      template instanceof Function\n        ? template({ updatePortal: () => updatePortal(curId) })","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/blocksuite/affine/components/src/portal/helper.ts#L26-L62","documentation":"createSimplePortal() attaches a shadow root to a wrapper div (when shadowDom is truthy) then reads portalRoot.shadowRoot. If that read returns null the function throws ValueNotExists. attachShadow can silently fail to populate shadowRoot on hosts that already have a shadow root, in environments lacking Shadow DOM support, or when the element is an invalid shadow host.","triggerScenarios":"Calling createSimplePortal with shadowDom=true (or an options object) in an environment where Shadow DOM is unavailable, or passing a custom element/tag that cannot host a shadow root.","commonSituations":"Running under jsdom/test environments without Shadow DOM polyfills; SSR where document APIs are stubbed; re-attaching a shadow root to an element that already has one.","solutions":["Ensure the runtime provides Shadow DOM (use a polyfill in jsdom/SSR tests).","Pass shadowDom=false to render into the light DOM instead.","Confirm createSimplePortal is called in a browser context after DOM is ready."],"exampleFix":"// before\ncreateSimplePortal({ template, shadowDom: true }); // fails in jsdom\n\n// after\ncreateSimplePortal({ template, shadowDom: false });","handlingStrategy":"validation","validationCode":"const supportsShadow = typeof Element !== 'undefined' && typeof Element.prototype.attachShadow === 'function';\ncreateSimplePortal({ template, shadowDom: supportsShadow });","typeGuard":"const canHostShadow = (el: Element): boolean => typeof el.attachShadow === 'function';","tryCatchPattern":null,"preventionTips":["Detect Shadow DOM support before enabling shadowDom option","Use shadowDom:false in jsdom/SSR tests"],"tags":["portal","dom","shadow-dom","rendering"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}