Budibase/budibase · error

mountBudibaseApp requires a target HTMLElement

Error message

mountBudibaseApp requires a target HTMLElement

What it means

mountBudibaseApp mounts a Budibase app into a DOM element. Its first validation requires a truthy target that is an instance of HTMLElement; anything else (null, undefined, a selector string, a non-element object) is rejected with this error before any app loading begins.

Source

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

  if (!app) {
    app = mount(ClientApp, {
      target,
    })
  }
}

// Attach to window so the HTML template can call this when it loads
window.loadBudibase = loadBudibase

export const mountBudibaseApp = async ({
  target,
  appUrl,
  appId,
  initialPath,
  onNavigate,
}: MountBudibaseAppOptions) => {
  if (!target || !(target instanceof HTMLElement)) {
    throw new Error("mountBudibaseApp requires a target HTMLElement")
  }

  const appPath = normalizeAppPath(appUrl)
  const appHash = getHash(appUrl)
  if (!appPath) {
    throw new Error("mountBudibaseApp requires a valid appUrl")
  }

  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

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Pass an actual DOM element: document.getElementById("root") or equivalent, and confirm it is non-null
  2. Call mountBudibaseApp after the DOM is ready (script at end of body, defer, or DOMContentLoaded listener)
  3. If using a selector, resolve it first: document.querySelector("#root")

Example fix

// before
mountBudibaseApp({ target: "#root", appUrl: "/my-app" })
// after
const el = document.getElementById("root")
mountBudibaseApp({ target: el, appUrl: "/my-app" })
Defensive patterns

Strategy: type-guard

Validate before calling

const el = document.getElementById("root")
if (!el || !(el instanceof HTMLElement)) {
  throw new Error("Mount target not found or not an HTMLElement")
}
mountBudibaseApp({ target: el, appUrl })

Type guard

const isMountTarget = (t: unknown): t is HTMLElement =>
  t instanceof HTMLElement

Try / catch

try {
  await mountBudibaseApp({ target: getTarget(), appUrl })
} catch (err) {
  if ((err as Error).message.includes("requires a target HTMLElement")) {
    // resolve element after DOM ready and retry once
  } else throw err
}

Prevention

When it happens

Trigger: Calling mountBudibaseApp with target omitted, null, a CSS selector string like "#root", or a non-HTMLElement object (e.g. a jQuery wrapper or the document).

Common situations: Calling before DOMContentLoaded so getElementById returns null; passing a query selector string instead of the element; querying the wrong container id; framework code passing a ref object rather than the DOM node.

Related errors


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