angular: Cannot read property 'bindingStartIndex' of null when using Library

šŸž bug report

Affected Package

Not sure. Maybe this is somewhere in @angular/cli or somewhere related to Webpack.

Is this a regression?

Yes, the previous version in which this bug was not present was Angular 8

Description

When creating a library as described in the documentation and using it in an empty app, I get the following error at runtime:

ERROR TypeError: Cannot read property 'bindingStartIndex' of null
at Module.ɵɵelementStart (core.js:20997)
at MyLibComponent_Template (my-lib.js:19)
at executeTemplate (core.js:11930)
at renderView (core.js:11716)
at renderComponent (core.js:13232)
at renderChildComponents (core.js:11519)
at renderView (core.js:11742)
at renderComponent (core.js:13232)
at renderChildComponents (core.js:11519)
at renderView (core.js:11742)

I do not see any errors while compiling.

šŸ”¬ Minimal Reproduction

I did the following:

  • Create a my-libs project: ng new my-libs --create-application=false
  • Create a library: cd my-libs and ng generate library my-lib
  • Create an app next to this: cd .. and ng new my-app
  • Add the library as a dependency of the app: Add "my-lib": "file:../my-libs/dist/my-lib" to the dependencies in the appā€™s package.json and run npm install
  • Import the MyLibModule in the AppModule (imported via import { MyLibModule } from 'my-lib';)
  • Use the component in the AppComponent: <lib-my-lib></lib-my-lib>
  • Build the library: cd my-libs and ng build --prod
  • Run the app: cd .. and ng serve
  • Point browser at http://localhost:4200/
  • Open Developer Tools to look at the console

The resulting project is contained in this zip-file repro.zip. I removed the node_modules, so please do

$ cd my-libs
$ npm install
$ ng build --prod
$ cd ..
$ cd my-app
$ npm install
$ ng serve

šŸ”„ Exception or Error


    ERROR TypeError: Cannot read property 'bindingStartIndex' of null
    at Module.ɵɵelementStart (core.js:20997)
    at MyLibComponent_Template (my-lib.js:19)
    at executeTemplate (core.js:11930)
    at renderView (core.js:11716)
    at renderComponent (core.js:13232)
    at renderChildComponents (core.js:11519)
    at renderView (core.js:11742)
    at renderComponent (core.js:13232)
    at renderChildComponents (core.js:11519)
    at renderView (core.js:11742)

šŸŒ Your Environment

Angular Version:


     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / ā–³ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 9.0.2
Node: 12.13.0
OS: darwin x64

Angular: 
... 
Ivy Workspace: 

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.900.2
@angular-devkit/core         9.0.2
@angular-devkit/schematics   9.0.2
@schematics/angular          9.0.2
@schematics/update           0.900.2
rxjs                         6.5.3

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 28
  • Comments: 26 (5 by maintainers)

Commits related to this issue

Most upvoted comments

in your angular app that depends on your local library, set projects.projectName.architect.build.options.preserveSymlinks with true in angular.json will prevent the angular cli from updating linked local library

This happens when @NgModule() is resolved from a different node_modules location.

Given this configuration, we can use my-lib from my-app directly without building my-lib:

# project directory structure
/
  /my-app
    /node_modules
    /projects
  /my-lib
    /node_modules
    /projects

# my-app's tsconfig.json:
    "paths": {
      "my-lib": [
        "../my-lib/projects/my-lib/src/public-api"
      ]
    }

As @mhevery highlighted, the error indicates that somehow there are two copies of Ivy in there. This was due to TypeScriptā€™s module resolution approach - it looks for node_modules by traversing up the directory of file being compiled.

To fix this, I tell Typescript where to find Angular packages by using:

    "paths": {
      "@angular/*": [
        "./node_modules/@angular/*"
      ],
      "my-lib": [
        "../my-lib/projects/my-lib/src/public-api"
      ]
    }

Initial test seems to be working. Hope this helps.

Also, I think this approach does not depend on preserveSymlinks or "enableIvy": false.

Specifying path to angular packages as @kctang mentioned was enough for me to fix the error, thank you for that. I just wanna point out that the path belongs in the compilerOptions section of appā€™s tsconfig.json file.

// app's tsconfig.json
{
  ...
  "compilerOptions": {
    ...
    "paths": {
      "@angular/*": [
        "./node_modules/@angular/*"
      ]
    }
  }
}

For now I guess Iā€™ll have to create a little schematic for my co-workers to spare them the trouble, but I really hope this gets fixed soon tho.

Edit: I should probably read documentation twice next time.

Edit2: Oh and specifying path to libā€™s source code to skip building is actually really useful. Big ups to @kctang for that as well!

Ok, this issue only happens when you link the library (or use file:... in your package.json).

When you build the library with ng build my-lib --prod and manually copy the dist/my-lib into node_modules/my-lib (thus not creating a symlink) the ng serve is not throwing an error and everything works.

If you use npm link, you can see that the original library folder (dist/my-lib) gets changed on ng serve, also the package.json will be modified, for example this is added:

  "scripts": {
    "prepublishOnly": "node --eval \"console.error('ERROR: Trying to publish a package that has been compiled by NGCC. This is not allowed.\\nPlease delete and rebuild the package, without compiling with NGCC, before attempting to publish.\\nNote that NGCC may have been run by importing this package into another project that is being built with Ivy enabled.\\n')\" && exit 1"
  }

The problem lies here somewhere. If you publish the package to npm (or github), this wonā€™t be an issue. I think if you create a read-only symlink to my-lib, this will work as it will not modify the original package?

In summary: npm link with custom libraries is currently broken (I think only with 9.x.x?). When ng serve is being run, the linked package gets modified and thus broken.

I have the same issue. I have different workspaces for library and app.

Iā€™ve been facing the same issue in a recent projectā€¦ In this case though

"preserveSymlinks": true,
"paths": {
  "@angular/*": ["./node_modules/@angular/*"]
}

Doesnā€™t help!

The difference with the other projects, where it worked is that in this case we are working with angular 17 with the new build system and vite

Does this now need a different workaround?

@00guille I got it working by adding this option to tsconfig.json of both the library repository and the main app repository:

  "angularCompilerOptions": {
    "enableIvy": false
  }

I havenā€™t tested all the possible configurations (like using Ivy in the main App and not using it in the library or vice versa).

I can now link the dependency locally and it works. Hope this helps for now.

it worked! but the idea is to be able to use ivy with the benefits that it carries

I hit the same issue trying to have a multi project setup with an ionic project and an angular project trying to share a common library.

this answer solved the problem for me but I was wondering if it has any downsides to directly referencing the library like " ā€œā€¦/my-lib/projects/my-lib/src/public-apiā€" rather than looking for the version in the dist folder.

Because this solves a couple of issue for me which I find very useful,

  1. not able to find all references from the library
  2. ā€œgo to definitionā€ you will end up in the dist folder than the actual code.

This happens when @NgModule() is resolved from a different node_modules location.

Given this configuration, we can use my-lib from my-app directly without building my-lib:

# project directory structure
/
  /my-app
    /node_modules
    /projects
  /my-lib
    /node_modules
    /projects

# my-app's tsconfig.json:
    "paths": {
      "my-lib": [
        "../my-lib/projects/my-lib/src/public-api"
      ]
    }

As @mhevery highlighted, the error indicates that somehow there are two copies of Ivy in there. This was due to TypeScriptā€™s module resolution approach - it looks for node_modules by traversing up the directory of file being compiled.

To fix this, I tell Typescript where to find Angular packages by using:

    "paths": {
      "@angular/*": [
        "./node_modules/@angular/*"
      ],
      "my-lib": [
        "../my-lib/projects/my-lib/src/public-api"
      ]
    }

Initial test seems to be working. Hope this helps.

Also, I think this approach does not depend on preserveSymlinks or "enableIvy": false.

Specifying path to angular packages as @kctang mentioned was enough for me to fix the error, thank you for that. I just wanna point out that the path belongs in the compilerOptions section of appā€™s tsconfig.json file.

// app's tsconfig.json
{
  ...
  "compilerOptions": {
    ...
    "paths": {
      "@angular/*": [
        "./node_modules/@angular/*"
      ]
    }
  }
}

For now I guess Iā€™ll have to create a little schematic for my co-workers to spare them the trouble, but I really hope this gets fixed soon tho.

Edit: I should probably read documentation twice next time.

Edit2: Oh and specifying path to libā€™s source code to skip building is actually really useful. Big ups to @kctang for that as well!

this actually fixed my same issue

I found out that the problem was that Iā€™m using the --prod option in my library build command the solution was to

  • remove the --prod option
  • set "preserveSymlinks": true and suggested here
  • and enable Ivy "enableIvy": true