{"record":{"id":"67139541c1737d96","repo":"ionic-team/ionic-framework","slug":"inserted-view-was-already-destroyed","errorCode":null,"errorMessage":"inserted view was already destroyed","messagePattern":"inserted view was already destroyed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/src/components/nav/nav.tsx","lineNumber":742,"sourceCode":"    if (!insertViews) {\n      return;\n    }\n    assert(insertViews.length > 0, 'length can not be zero');\n    const viewControllers = convertToViews(insertViews);\n\n    if (viewControllers.length === 0) {\n      throw new Error('invalid views to insert');\n    }\n\n    // Check all the inserted view are correct\n    for (const view of viewControllers) {\n      view.delegate = ti.opts.delegate;\n      const nav = view.nav;\n      if (nav && nav !== this) {\n        throw new Error('inserted view was already inserted');\n      }\n      if (view.state === VIEW_STATE_DESTROYED) {\n        throw new Error('inserted view was already destroyed');\n      }\n    }\n    ti.insertViews = viewControllers;\n  }\n\n  /**\n   * Returns the view that will be entered considering the transition instructions.\n   *\n   * @param ti The instructions.\n   * @param leavingView The view being left or undefined if none.\n   *\n   * @returns The view that will be entered, undefined if none.\n   */\n  private getEnteringView(\n    ti: TransitionInstruction,\n    leavingView: ViewController | undefined\n  ): ViewController | undefined {\n    // The last inserted view will be entered when view are inserted.","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/ionic-team/ionic-framework/blob/625f9c38ad8c5db8a6c12df5c1622a36da90f9e3/core/src/components/nav/nav.tsx#L724-L760","documentation":"Thrown in IonNav.prepareTI() when an inserted view's `state` is `VIEW_STATE_DESTROYED`. Once a view has been destroyed (removed and torn down by the nav), it cannot be re-inserted because its DOM and lifecycle resources are gone. The nav refuses to revive a destroyed controller.","triggerScenarios":"Passing a ViewController that was previously popped (and thus destroyed) back into `insert`/`push`/`setPages`/`setRoot`; caching a view reference and reusing it after the nav destroyed it.","commonSituations":"Holding a reference from `nav.getActive()` or `nav.getByIndex()`, popping the view, then trying to push the same controller again; pooling/caching views for performance and reusing them after destruction.","solutions":["Never re-insert a destroyed ViewController; always insert the component class/element and let the nav build a new view.","Discard cached controller references once the view has been popped.","If you need stateful reuse, store the component props and re-create the view via setRoot/push with those props.","Audit for any code path that retains `getActive()`/`getByIndex()` results across pop operations."],"exampleFix":"// before\nconst view = nav.getActive();\nawait nav.pop();\nawait nav.push(view); // view is destroyed -> throws\n// after\nconst { component, componentProps } = view;\nawait nav.pop();\nawait nav.push(component, componentProps);","handlingStrategy":"validation","validationCode":"// Do not re-insert destroyed views; check state if you must reuse a reference\nimport { VIEW_STATE_DESTROYED } from '@ionic/core'; // conceptual\nif (viewController.state === VIEW_STATE_DESTROYED) {\n  throw new Error('Cannot re-insert a destroyed view. Push its component instead.');\n}\nawait nav.push(viewController.component, viewController.componentProps);","typeGuard":"function isLiveView(view: ViewController): boolean {\n  return view && view.state !== VIEW_STATE_DESTROYED;\n}","tryCatchPattern":null,"preventionTips":["Discard controller references once a view is popped.","Re-create views from their component + props, not from cached controllers.","Avoid view-pooling strategies that retain destroyed controllers."],"tags":["core","ion-nav","navigation","lifecycle"],"backgroundTag":null,"analyzedSha":"625f9c38ad8c5db8a6c12df5c1622a36da90f9e3","analyzedAt":"2026-08-12T16:00:25.413Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}