{"record":{"id":"b65fa35f99160de2","repo":"angular/angular","slug":"upgraded-directive-this-directive-name-specif","errorCode":null,"errorMessage":"Upgraded directive '${this.directive.name}' specifies 'bindToController' but no controller.","messagePattern":"Upgraded directive '(.+?)' specifies 'bindToController' but no controller\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/upgrade/static/src/upgrade_component.ts","lineNumber":145,"sourceCode":"  ngOnInit() {\n    // Collect contents, insert and compile template\n    const attachChildNodes: ɵangular1.ILinkFn | undefined = this.helper.prepareTransclusion();\n    const linkFn = this.helper.compileTemplate();\n\n    // Instantiate controller\n    const controllerType = this.directive.controller;\n    const bindToController = this.directive.bindToController;\n    let controllerInstance = controllerType\n      ? this.helper.buildController(controllerType, this.$componentScope)\n      : undefined;\n    let bindingDestination: ɵupgradeHelper.IBindingDestination;\n\n    if (!bindToController) {\n      bindingDestination = this.$componentScope;\n    } else if (controllerType && controllerInstance) {\n      bindingDestination = controllerInstance;\n    } else {\n      throw new Error(\n        `Upgraded directive '${this.directive.name}' specifies 'bindToController' but no controller.`,\n      );\n    }\n    this.controllerInstance = controllerInstance;\n    this.bindingDestination = bindingDestination;\n\n    // Set up outputs\n    this.bindOutputs(bindingDestination);\n\n    // Require other controllers\n    const requiredControllers = this.helper.resolveAndBindRequiredControllers(controllerInstance);\n\n    // Hook: $onChanges\n    if (this.pendingChanges) {\n      this.forwardChanges(this.pendingChanges, bindingDestination);\n      this.pendingChanges = null;\n    }\n","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/upgrade/static/src/upgrade_component.ts#L127-L163","documentation":"Thrown by UpgradeComponent.ngOnInit() (upgrade_component.ts:145) when the upgraded AngularJS directive sets 'bindToController' (truthy) but defines no 'controller'. Bindings declared with bindToController must land on a controller instance; with no controller there is nowhere to put them, so the upgrader refuses to proceed.","triggerScenarios":"Wrapping with UpgradeComponent an AngularJS directive that has bindToController: true (or a bindings object) but no controller property; also when the controller is falsy (e.g. undefined due to DDO manipulation).","commonSituations":"Upgrading component-style directives written for AngularJS 1.5+ where the author moved bindings to bindToController but the controller was accidentally removed, renamed, or conditionally defined.","solutions":["Add a controller to the AngularJS directive so bindToController bindings have a destination.","Remove 'bindToController' and put binding definitions back on 'scope' if no controller is intended.","Prefer migrating the directive to a true AngularJS 1.5 'component()' definition (which enforces controller presence) before upgrading."],"exampleFix":"// before\nangular.module('h').directive('heroDetail', () => ({\n  bindToController: true,\n  scope: {hero: '='},\n  template: '<span>{{ctrl.hero.name}}</span>',\n}));\n\n// after\nangular.module('h').directive('heroDetail', () => ({\n  bindToController: true,\n  controller: class { hero: any; },\n  controllerAs: 'ctrl',\n  scope: {hero: '='},\n  template: '<span>{{ctrl.hero.name}}</span>',\n}));","handlingStrategy":"type-guard","validationCode":"// Screen directives before wrapping them\nconst ddo = $injector.get('heroDetailDirective')[0];\nif (ddo.bindToController && !ddo.controller) { throw new Error('Directive needs a controller for bindToController.'); }","typeGuard":"function hasControllerForBindings(d: any): boolean { return !d.bindToController || !!d.controller; }","tryCatchPattern":null,"preventionTips":["Adopt AngularJS 1.5 component() definitions before upgrading; they always pair bindings with a controller.","Lint directives for bindToController without controller."],"tags":["angular","angularjs","upgrade","directive","bindings"],"backgroundTag":"angularjs-upgrade-unsupported-directive-feature","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}