{"record":{"id":"4f1f59aa65fcdb52","repo":"different-ai/openwork","slug":"config-name-root-element-is-missing","errorCode":null,"errorMessage":"${config.name} root element is missing.","messagePattern":"(.+?) root element is missing\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp-apps/src/shared/bridge.tsx","lineNumber":52,"sourceCode":"        }\n        createdApp.ontoolcancelled = ({ reason }) => {\n          setResultError(reason ?? \"The tool call was cancelled.\")\n        }\n      },\n    })\n    useHostStyles(app, app?.getHostContext())\n\n    if (error || resultError) {\n      return <StatusCard>{error?.message ?? resultError}</StatusCard>\n    }\n    if (!payload) {\n      return <StatusCard>{config.waitingLabel}</StatusCard>\n    }\n    return <>{config.render(payload, app)}</>\n  }\n\n  const root = document.getElementById(\"root\")\n  if (!root) throw new Error(`${config.name} root element is missing.`)\n  createRoot(root).render(\n    <StrictMode>\n      <AppRoot />\n    </StrictMode>,\n  )\n}\n","sourceCodeStart":34,"sourceCodeEnd":59,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/packages/mcp-apps/src/shared/bridge.tsx#L34-L59","documentation":"mountMcpApp renders the MCP App's React tree into the DOM element with id \"root\". If that element is absent when mounting, it throws with the app config's name, because createRoot requires a real container element. This is a host-page integration error, not a React error.","triggerScenarios":"Calling mountMcpApp({ config }) in a document whose HTML lacks <div id=\"root\">, mounting before DOMContentLoaded (script runs in <head>), or mounting into a shadow root/DOM where the root node has a different id.","commonSituations":"Vite/webpack dev server serving the built bundle before index.html's root div exists; host page embedding the MCP app inside a custom container with a different id; React 18+ createRoot stricter than legacy ReactDOM.render which auto-created containers.","solutions":["Ensure the host HTML contains <div id=\"root\"></div> before the app script executes.","Defer mounting until the DOM is ready: wrap mountMcpApp in DOMContentLoaded or place the script tag at the end of <body> with type=module/defer.","If the host uses a different container id, add/adjust the root lookup in the mount config or template.","If mounting into shadow DOM, mount on the shadow root's element rather than relying on document.getElementById."],"exampleFix":"// before\n<script type=\"module\" src=\"/src/main.tsx\"></script>\n// after\n<div id=\"root\"></div>\n<script type=\"module\" src=\"/src/main.tsx\"></script>","handlingStrategy":"validation","validationCode":"if (!document.getElementById(\"root\")) throw new Error(\"Host page must include <div id=\\\"root\\\"></div>\");\nmountMcpApp({ config });","typeGuard":"function hasRoot(doc: Document): boolean {\n  return doc.getElementById(\"root\") !== null;\n}","tryCatchPattern":"try {\n  mountMcpApp({ config });\n} catch (e) {\n  if (e.message.endsWith(\"root element is missing.\")) renderFallbackInto(document.body);\n  else throw e;\n}","preventionTips":["Always ship <div id=\"root\"></div> in the host HTML template","Mount after DOMContentLoaded or use defer/module scripts","Agree on one container id convention between host pages and MCP apps"],"tags":["react","dom","mounting","mcp-apps"],"backgroundTag":"missing-root-element","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}