Budibase/budibase · error

Budibase is already mounted. Unmount the existing instance b

Error message

Budibase is already mounted. Unmount the existing instance before mounting again.

What it means

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.

Source

Thrown at packages/client/src/index.ts:346

  }

  const resolvedAppId = appId || (await resolveAppIdFromPath(appPath))

  window["##BUDIBASE_APP_ID##"] = resolvedAppId
  window["##BUDIBASE_EMBED_LOCATION##"] = appPath

  const resolvedInitialPath = initialPath
    ? normalizeRoutePath(initialPath)
    : appHash
      ? normalizeRoutePath(appHash.replace(/^#/, ""))
      : undefined

  if (resolvedInitialPath && getCurrentPath() !== resolvedInitialPath) {
    await navigateToPath(resolvedInitialPath)
  }

  if (app) {
    throw new Error(
      "Budibase is already mounted. Unmount the existing instance before mounting again."
    )
  }
  await loadBudibase({
    target,
  })

  const notifyNavigation = onNavigate
    ? () => onNavigate(getCurrentPath())
    : undefined
  if (notifyNavigation) {
    window.addEventListener("hashchange", notifyNavigation)
    notifyNavigation()
  }

  const handle = (() => {
    if (notifyNavigation) {
      window.removeEventListener("hashchange", notifyNavigation)

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Call the returned unmount/cleanup function from the first mount before calling mountBudibaseApp again.
  2. Wrap the mount in a guard: only mount if the SDK has not been initialized yet (module-level flag or check for existing instance).
  3. If remounting the same app, reuse the existing instance instead of creating a new one.

Example fix

// before
useEffect(() => {
  mountBudibaseApp(...) // re-runs on every render
})
// after
useEffect(() => {
  const instance = mountBudibaseApp(...)
  return () => instance.unmount()
}, [])
Defensive patterns

Strategy: try-catch

Validate before calling

if (window["~budibase"]?.app || window.__budibaseMounted) {
  return window.__budibaseInstance
}

Type guard

function isMounted(): boolean {
  return Boolean((window as any)["~budibase"]?.app)
}

Try / catch

try {
  const instance = await mountBudibaseApp(...)
} catch (e) {
  if (e.message.includes("already mounted")) {
    // reuse existing instance or unmount first
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/0a5cd3c02c8579f8. Report an issue: GitHub.