{"record":{"id":"0a5cd3c02c8579f8","repo":"Budibase/budibase","slug":"budibase-is-already-mounted-unmount-the-existing","errorCode":null,"errorMessage":"Budibase is already mounted. Unmount the existing instance before mounting again.","messagePattern":"Budibase is already mounted\\. Unmount the existing instance before mounting again\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/client/src/index.ts","lineNumber":346,"sourceCode":"  }\n\n  const resolvedAppId = appId || (await resolveAppIdFromPath(appPath))\n\n  window[\"##BUDIBASE_APP_ID##\"] = resolvedAppId\n  window[\"##BUDIBASE_EMBED_LOCATION##\"] = appPath\n\n  const resolvedInitialPath = initialPath\n    ? normalizeRoutePath(initialPath)\n    : appHash\n      ? normalizeRoutePath(appHash.replace(/^#/, \"\"))\n      : undefined\n\n  if (resolvedInitialPath && getCurrentPath() !== resolvedInitialPath) {\n    await navigateToPath(resolvedInitialPath)\n  }\n\n  if (app) {\n    throw new Error(\n      \"Budibase is already mounted. Unmount the existing instance before mounting again.\"\n    )\n  }\n  await loadBudibase({\n    target,\n  })\n\n  const notifyNavigation = onNavigate\n    ? () => onNavigate(getCurrentPath())\n    : undefined\n  if (notifyNavigation) {\n    window.addEventListener(\"hashchange\", notifyNavigation)\n    notifyNavigation()\n  }\n\n  const handle = (() => {\n    if (notifyNavigation) {\n      window.removeEventListener(\"hashchange\", notifyNavigation)","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/client/src/index.ts#L328-L364","documentation":"mountBudibaseApp guards against double-mounting: it keeps a module-level `app` reference and throws if a client instance is already attached to the page. Budibase embeds only support one mounted app instance per document, so calling mount again without unmounting is rejected instead of silently corrupting state.","triggerScenarios":"Calling window['~budibase'].loadBudibaseCSS() / mountBudibaseApp twice (e.g. re-invoking the embed snippet on SPA route change) or remounting after a failed unmount where the module-level `app` variable was never cleared.","commonSituations":"React/Vue hot module reload re-running the embed script; embedding the same Budibase app in two container divs; a parent component re-rendering and re-executing the mount script; calling mount inside a component body instead of once on mount lifecycle.","solutions":["Call the returned unmount/cleanup function from the first mount before calling mountBudibaseApp again.","Wrap the mount in a guard: only mount if the SDK has not been initialized yet (module-level flag or check for existing instance).","If remounting the same app, reuse the existing instance instead of creating a new one."],"exampleFix":"// before\nuseEffect(() => {\n  mountBudibaseApp(...) // re-runs on every render\n})\n// after\nuseEffect(() => {\n  const instance = mountBudibaseApp(...)\n  return () => instance.unmount()\n}, [])","handlingStrategy":"try-catch","validationCode":"if (window[\"~budibase\"]?.app || window.__budibaseMounted) {\n  return window.__budibaseInstance\n}","typeGuard":"function isMounted(): boolean {\n  return Boolean((window as any)[\"~budibase\"]?.app)\n}","tryCatchPattern":"try {\n  const instance = await mountBudibaseApp(...)\n} catch (e) {\n  if (e.message.includes(\"already mounted\")) {\n    // reuse existing instance or unmount first\n  } else {\n    throw e\n  }\n}","preventionTips":["Mount once at app bootstrap, not in render paths","Always pair mount with unmount in lifecycle cleanup","Use a module-level initialization flag for the embed script","Disable script re-execution under HMR in dev"],"tags":["client","lifecycle","double-mount"],"backgroundTag":"double-mount-attempt","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}