{"record":{"id":"d7f40c26607a09c1","repo":"angular/components","slug":"a-mat-tab-nav-panel-must-be-specified-via-tabpane","errorCode":null,"errorMessage":"A mat-tab-nav-panel must be specified via [tabPanel].","messagePattern":"A mat-tab-nav-panel must be specified via \\[tabPanel\\]\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/material/tabs/tab-nav-bar/tab-nav-bar.ts","lineNumber":199,"sourceCode":"  override ngAfterContentInit() {\n    this._inkBar = new MatInkBar(this._items);\n    // We need this to run before the `changes` subscription in parent to ensure that the\n    // selectedIndex is up-to-date by the time the super class starts looking for it.\n    this._items.changes\n      .pipe(startWith(null), takeUntil(this._destroyed))\n      .subscribe(() => this.updateActiveLink());\n\n    super.ngAfterContentInit();\n\n    // Turn the `change` stream into a signal to try and avoid \"changed after checked\" errors.\n    this._keyManager!.change.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() =>\n      this._focusedItem.set(this._keyManager?.activeItem || null),\n    );\n  }\n\n  override ngAfterViewInit() {\n    if (!this.tabPanel && (typeof ngDevMode === 'undefined' || ngDevMode)) {\n      throw new Error('A mat-tab-nav-panel must be specified via [tabPanel].');\n    }\n    super.ngAfterViewInit();\n  }\n\n  /** Notifies the component that the active link has been changed. */\n  updateActiveLink() {\n    if (!this._items) {\n      return;\n    }\n\n    const items = this._items.toArray();\n\n    for (let i = 0; i < items.length; i++) {\n      if (items[i].active) {\n        this.selectedIndex = i;\n        if (this.tabPanel) {\n          this.tabPanel._activeTabId = items[i].id;\n        }","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/material/tabs/tab-nav-bar/tab-nav-bar.ts#L181-L217","documentation":"MatTabNav (the nav-bar variant of tabs) requires its associated MatTabNavPanel so it can compute and position the ink bar over the correct panel region. The component validates this in ngAfterViewInit: if the `[tabPanel]` input was never bound, it throws in dev mode instead of silently rendering a broken ink bar.","triggerScenarios":"Rendering `<nav mat-tab-nav-bar>` without `[tabPanel]=\"panelRef\"` where panelRef is a template ref to a `<mat-tab-nav-panel>`.","commonSituations":"Migrating from the old MatTabNav API (which used a different panel wiring) to the current one; forgetting the <mat-tab-nav-panel> wrapper element when converting mat-tab-group to nav-bar style tabs; typos in the template ref variable name.","solutions":["Add a <mat-tab-nav-panel> element wrapping the tab content","Bind [tabPanel] on <nav mat-tab-nav-bar> to the panel's template reference variable","Ensure the template ref variable name matches exactly (e.g. #tabPanel)","Verify the MatTabNavPanel import from @angular/material/tabs is used, not a plain div"],"exampleFix":"// before\n<nav mat-tab-nav-bar>\n  <a mat-tab-link ...>Link</a>\n</nav>\n<router-outlet></router-outlet>\n\n// after\n<nav mat-tab-nav-bar [tabPanel]=\"tabPanel\">\n  <a mat-tab-link ...>Link</a>\n</nav>\n<mat-tab-nav-panel #tabPanel>\n  <router-outlet></router-outlet>\n</mat-tab-nav-panel>","handlingStrategy":"validation","validationCode":"// In the component/test, verify wiring before render\n@ViewChild('tabPanel') tabPanel?: MatTabNavPanel;\nassert(this.tabPanel != null, 'tabPanel must be bound to <mat-tab-nav-panel>');","typeGuard":"function hasTabPanel(nav: {tabPanel?: MatTabNavPanel}): nav is {tabPanel: MatTabNavPanel} {\n  return nav.tabPanel != null;\n}","tryCatchPattern":"try {\n  this.nav.ngAfterViewInit();\n} catch (e) {\n  if (String(e?.message).includes('mat-tab-nav-panel')) {\n    console.error('Bind [tabPanel] to a <mat-tab-nav-panel #ref> element.');\n  }\n}","preventionTips":["Always pair <nav mat-tab-nav-bar> with a <mat-tab-nav-panel> and [tabPanel] binding","Name the template ref clearly (e.g. #tabPanel) and bind it in the same template","Add a unit test that instantiates the nav bar and asserts no throw","Review migration notes when moving from older MatTabNav APIs"],"tags":["angular-material","tabs","template-error","dev-mode"],"backgroundTag":"missing-required-input","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}