{"record":{"id":"4e9da4c5c0457244","repo":"TanStack/query","slug":"devtools-is-already-mounted-4e9da4","errorCode":null,"errorMessage":"Devtools is already mounted","messagePattern":"Devtools is already mounted","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/query-devtools/src/TanstackQueryDevtoolsPanel.tsx","lineNumber":103,"sourceCode":"  setErrorTypes(errorTypes: Array<DevtoolsErrorType>) {\n    this.#errorTypes[1](errorTypes)\n  }\n\n  setClient(client: QueryClient) {\n    this.#client[1](client)\n  }\n\n  setOnClose(onClose: () => void) {\n    this.#onClose[1](() => onClose)\n  }\n\n  setTheme(theme?: Theme) {\n    this.#theme[1](theme)\n  }\n\n  mount<T extends HTMLElement>(el: T) {\n    if (this.#isMounted) {\n      throw new Error('Devtools is already mounted')\n    }\n    const dispose = render(() => {\n      const [btnPosition] = this.#buttonPosition\n      const [pos] = this.#position\n      const [isOpen] = this.#initialIsOpen\n      const [errors] = this.#errorTypes\n      const [hideDisabledQueries] = this.#hideDisabledQueries\n      const [queryClient] = this.#client\n      const [onClose] = this.#onClose\n      const [theme] = this.#theme\n      let Devtools: DevtoolsComponentType\n\n      if (this.#Component) {\n        Devtools = this.#Component\n      } else {\n        Devtools = lazy(() => import('./DevtoolsPanelComponent'))\n        this.#Component = Devtools\n      }","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/TanStack/query/blob/159982c80b844487054155c38ffc760fe4208daf/packages/query-devtools/src/TanstackQueryDevtoolsPanel.tsx#L85-L121","documentation":"Thrown by `TanstackQueryDevtoolsPanel.mount()` (the standalone panel variant of the vanilla devtools class, used for embedding the devtools panel without the floating button) when `mount` is called on an already-mounted instance. Same single-mount constraint as the full devtools: the class renders Solid into one container and tracks a single `#isMounted` flag.","triggerScenarios":"Calling `panel.mount(el)` twice on the same `TanstackQueryDevtoolsPanel` instance without an intervening `unmount()`. Typical when embedding the panel in a custom container whose mount effect re-runs (StrictMode, route change, HMR) or when reusing a panel instance across views.","commonSituations":"React 18 StrictMode double-mounting; route-based remounts in SPAs that reuse one panel instance; embedding the panel inside a web component whose `connectedCallback` fires more than once across reconnections.","solutions":["Pair every `mount()` with an `unmount()` in cleanup: `useEffect(() => { panel.mount(el); return () => panel.unmount() }, [])`.","Create a new `TanstackQueryDevtoolsPanel` instance per mount target.","Guard with your own `isMounted` flag before calling `mount()`.","If using the panel inside React, prefer `<ReactQueryDevtoolsPanel />` which manages mount/unmount internally."],"exampleFix":"// before - panel mounted twice on route change\npanel.mount(hostEl)\n\n// after - unmount before remounting\npanel.unmount()\npanel.mount(hostEl)","handlingStrategy":"validation","validationCode":"let panelMounted = false\nconst mountPanel = (panel, el) => {\n  if (panelMounted) return\n  panel.mount(el)\n  panelMounted = true\n}","typeGuard":"const isPanelMountable = (p: { mount(el: HTMLElement): unknown }) =>\n  !(p as unknown as { _isMounted?: boolean })._isMounted","tryCatchPattern":"try {\n  panel.mount(el)\n} catch (e) {\n  if (e.message === 'Devtools is already mounted') return\n  throw e\n}","preventionTips":["Pair panel.mount() with panel.unmount() in the same effect.","Prefer the framework-specific <ReactQueryDevtoolsPanel /> component.","Create a new TanstackQueryDevtoolsPanel instance per mount target.","Guard mount() with your own mounted flag in StrictMode or remount-heavy lifecycles."],"tags":["devtools","panel","mount","lifecycle","vanilla"],"backgroundTag":null,"analyzedSha":"159982c80b844487054155c38ffc760fe4208daf","analyzedAt":"2026-08-12T16:21:52.822Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}