{"record":{"id":"0ac3bf0042206c6c","repo":"Eugeny/tabby","slug":"did-not-find-any-bootstrap-components-are-there-a","errorCode":null,"errorMessage":"Did not find any bootstrap components. Are there any plugins installed?","messagePattern":"Did not find any bootstrap components\\. Are there any plugins installed\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"app/src/app.module.ts","lineNumber":23,"sourceCode":"\nexport function getRootModule (plugins: any[]) {\n    const imports = [\n        BrowserModule,\n        ...plugins,\n        ToastrModule.forRoot({\n            positionClass: 'toast-bottom-center',\n            toastClass: 'toast',\n            preventDuplicates: true,\n            extendedTimeOut: 1000,\n        }),\n    ]\n\n    const bootstrap = [\n        ...plugins.filter(x => x.bootstrap).map(x => x.bootstrap),\n    ]\n\n    if (bootstrap.length === 0) {\n        throw new Error('Did not find any bootstrap components. Are there any plugins installed?')\n    }\n\n    @NgModule({\n        imports,\n    }) class RootModule {\n        ngDoBootstrap (appRef: ApplicationRef) {\n            (window as any)['requestAnimationFrame'] = window[window['Zone'].__symbol__('requestAnimationFrame')]\n\n            const componentDef = bootstrap[0]\n            appRef.bootstrap(componentDef)\n        }\n    }\n\n    return RootModule\n}\n","sourceCodeStart":5,"sourceCodeEnd":39,"githubUrl":"https://github.com/Eugeny/tabby/blob/14e2d60b9b6dee84a53c37f05eefeb803787de04/app/src/app.module.ts#L5-L39","documentation":"Thrown at application bootstrap time when no plugin contributes a component marked with a `bootstrap` field. The app module collects every plugin's `bootstrap` array and fails hard if the resulting list is empty, because Angular's manual bootstrap (appRef.bootstrap) requires at least one root component. This guards against shipping a build with no UI entry point.","triggerScenarios":"The `plugins` array (the app module's `imports`) contains zero plugins whose `bootstrap` property is truthy. This happens when plugins are loaded but none exports a root component, or when the plugin loader returns an empty list (e.g. broken plugin discovery, empty plugin folder, wrong plugin entry path).","commonSituations":"A fresh checkout where built-in UI plugins were not compiled/linked yet; a custom build that excluded the default `tabby-terminal`/`tabby-core` UI plugin; a packaging bug where `plugins` is filtered to nothing; running the app before `npm run build` for plugins; a plugin manifest that omits the `bootstrap` export.","solutions":["Verify at least one plugin exports a `bootstrap` component (e.g. the default UI plugin like tabby-terminal or the main window plugin) and that it is included in the `imports` array fed to RootModule.","Rebuild plugins: run the project's build step (e.g. `npm run build` / plugin build script) so plugin manifests and their `bootstrap` exports are generated.","If writing a custom host, add your own root component to a plugin's `bootstrap` array so the bootstrap list is non-empty.","Inspect the loaded `plugins` array at runtime (log `plugins.map(p => p.bootstrap)`) to confirm which plugin is missing the export, then fix that plugin's entry file."],"exampleFix":"// before\nconst bootstrap = [...plugins.filter(x => x.bootstrap).map(x => x.bootstrap)]\nif (bootstrap.length === 0) throw new Error('Did not find any bootstrap components...')\n\n// after - ensure a UI plugin with a bootstrap component is registered\nimport { TerminalTabComponent } from 'tabby-terminal'\nconst plugins = [...loadedPlugins]\nif (!plugins.some(p => p.bootstrap)) {\n    plugins.push({ bootstrap: [TerminalTabComponent] } as any)\n}","handlingStrategy":"validation","validationCode":"import { Type } from '@angular/core'\n\nfunction assertHasBootstrap (plugins: any[]): void {\n    const bootstrap = plugins.filter(p => p?.bootstrap).flatMap(p => p.bootstrap)\n    if (bootstrap.length === 0) {\n        throw new Error(\n            `No bootstrap component. Loaded ${plugins.length} plugin(s): ` +\n            plugins.map(p => p?.name ?? '<anonymous>').join(', '),\n        )\n    }\n}\n\n// run before constructing RootModule\nassertHasBootstrap(plugins)","typeGuard":"function pluginHasBootstrap (p: any): p is { bootstrap: any[] } {\n    return Array.isArray(p?.bootstrap) ? p.bootstrap.length > 0 : Boolean(p?.bootstrap)\n}","tryCatchPattern":null,"preventionTips":["Run the plugin build step before launching the app so plugin manifests and bootstrap exports exist.","Include at least one UI plugin that exports a bootstrap component in every build configuration.","Add a unit test asserting the default plugin set yields a non-empty bootstrap list.","Log the loaded plugin names early in bootstrap so a missing plugin is obvious in CI logs."],"tags":["angular","bootstrap","plugins","startup","configuration"],"backgroundTag":null,"analyzedSha":"14e2d60b9b6dee84a53c37f05eefeb803787de04","analyzedAt":"2026-08-12T11:46:48.773Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}