{"record":{"id":"6b100f0f24dae27d","repo":"Budibase/budibase","slug":"mountbudibaseapp-requires-a-target-htmlelement","errorCode":null,"errorMessage":"mountBudibaseApp requires a target HTMLElement","messagePattern":"mountBudibaseApp requires a target HTMLElement","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/client/src/index.ts","lineNumber":321,"sourceCode":"  if (!app) {\n    app = mount(ClientApp, {\n      target,\n    })\n  }\n}\n\n// Attach to window so the HTML template can call this when it loads\nwindow.loadBudibase = loadBudibase\n\nexport const mountBudibaseApp = async ({\n  target,\n  appUrl,\n  appId,\n  initialPath,\n  onNavigate,\n}: MountBudibaseAppOptions) => {\n  if (!target || !(target instanceof HTMLElement)) {\n    throw new Error(\"mountBudibaseApp requires a target HTMLElement\")\n  }\n\n  const appPath = normalizeAppPath(appUrl)\n  const appHash = getHash(appUrl)\n  if (!appPath) {\n    throw new Error(\"mountBudibaseApp requires a valid appUrl\")\n  }\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","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/client/src/index.ts#L303-L339","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Pass an actual DOM element: document.getElementById(\"root\") or equivalent, and confirm it is non-null","Call mountBudibaseApp after the DOM is ready (script at end of body, defer, or DOMContentLoaded listener)","If using a selector, resolve it first: document.querySelector(\"#root\")"],"exampleFix":"// before\nmountBudibaseApp({ target: \"#root\", appUrl: \"/my-app\" })\n// after\nconst el = document.getElementById(\"root\")\nmountBudibaseApp({ target: el, appUrl: \"/my-app\" })","handlingStrategy":"type-guard","validationCode":"const el = document.getElementById(\"root\")\nif (!el || !(el instanceof HTMLElement)) {\n  throw new Error(\"Mount target not found or not an HTMLElement\")\n}\nmountBudibaseApp({ target: el, appUrl })","typeGuard":"const isMountTarget = (t: unknown): t is HTMLElement =>\n  t instanceof HTMLElement","tryCatchPattern":"try {\n  await mountBudibaseApp({ target: getTarget(), appUrl })\n} catch (err) {\n  if ((err as Error).message.includes(\"requires a target HTMLElement\")) {\n    // resolve element after DOM ready and retry once\n  } else throw err\n}","preventionTips":["Wait for DOMContentLoaded (or place script with defer) before mounting","Pass the DOM node itself, never a selector string or framework ref object","Assert the container element exists in dev to fail fast"],"tags":["client-sdk","embedding","dom","argument-validation"],"backgroundTag":"invalid-argument","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}