Ids is not a constructor

I am having a hard time to find the cause of the following issue:
When the user tries to add a form field or an execution listener the following error is thrown:
Utils.js:201 Uncaught TypeError: Ids is not a constructor
at Object.nextId (Utils.js:201)
at generateElementId (ExtensionElements.js:30)
at Object.createElement (ExtensionElements.js:181)
at PropertiesPanel.executeAction (PropertiesPanel.js:696)
at HTMLDivElement.onClick (PropertiesPanel.js:574)
at HTMLDivElement. (index.js:360)

The problem is this is only reproducible on a specific environment and not on my local environment where I just run the app node style.
This specific environment is a Tomcat afaik. The JS bundle of the modeler is built in a JEE app.

I also know that before upgrading the following packages everything was fine:
“bpmn-js”: “^2.5.2”, -> “^3.1.0”,
“diagram-js”: “^2.6.1”, -> “^3.0.0”,
“bpmn-js-properties-panel”: “0.24.1”, -> “0.29.0”,
“bpmn-js-token-simulation”: “0.6.0”, -> “0.7.0”

In bpmn-js-properties-panel I had to add back the babel-preset-env package manually due to a bug, but I don’t think this could be the problem.

I know you can say ‘Hey if its working locally then the problem is on that specific environment’ but please at least try to give a hint where to look.

Thank you very much!

This seems to be an issue with importing the ids library. You’ll need an ES module aware bundler to properly import it.

Thank you! As you can see I am using babelify and before the version upgrade it worked like this:

"devDependencies": {
    "babel-core": "^6.26.0",
    "babel-preset-env": "^1.7.0",
    "babelify": "^8.0.0",
    "browserify": "^16.2.3",
    "eslint": "^4.18.1",
    "eslint-plugin-bpmn-io": "^0.4.1",
    "grunt": "^1.0.3",
    "grunt-browserify": "^5.0.0",
    "grunt-cli": "^1.3.2",
    "grunt-contrib-connect": "~1.0.2",
    "grunt-contrib-copy": "~1.0.0",
    "grunt-contrib-less": "^1.0.1",
    "grunt-contrib-watch": "~1.0.0",
    "load-grunt-tasks": "~3.5.0",
    "npm-run-all": "^4.1.3",
    "stringify": "^3.1.0",
    "time-grunt": "^0.3.2",
    "watchify": "^3.10.0"
  },
  "dependencies": {
    "bpmn-js": "^3.1.0",
    "bpmn-js-properties-panel": "file:C:/repositories/bpmn-js-properties-panel",
    "bpmn-js-token-simulation": "file:C:/repositories/bpmn-js-token-simulation",
    "camunda-bpmn-moddle": "^3.0.0",
    "diagram-js": "^3.0.0",
    "diagram-js-origin": "^1.2.0",
    "inherits": "^2.0.1",
    "jquery": "^3.3.1",
    "min-dash": "^3.2.0",
    "min-dom": "^3.1.1",
    "tiny-svg": "^2.2.0"
  }

I am also using global babelify transform, see my Gruntfile.js:

var path = require('path');

module.exports = function(grunt) {

  require('load-grunt-tasks')(grunt);
  require('time-grunt')(grunt);

  /**
   * Resolve external project resource as file path
   */
  function resolvePath(project, file) {
    return path.join(path.dirname(require.resolve(project)), file);
  }

  grunt.initConfig({
    config: {
      dist: '../../resources/bpmn'
    },
    browserify: {
      options: {
        browserifyOptions: {
          debug: true
        },
        transform: [
          [ 'stringify', {
            extensions: [ '.bpmn' ]
          } ],
          [ 'babelify', {
            global: true
          } ]
        ]
      },
      watch: {
        options: {
          watch: true
        },
        files: {
          '<%= config.dist %>/modeler.js': [ 'app/**/modeler.js' ],
          '<%= config.dist %>/viewer.js': [ 'app/**/viewer.js' ]
        }
      },
      app: {
        files: {
          '<%= config.dist %>/modeler.js': [ 'app/**/modeler.js' ],
          '<%= config.dist %>/viewer.js': [ 'app/**/viewer.js' ]
        }
      }
    },

    copy: {
      bpmn_js: {
        files: [
          {
            expand: true,
            cwd: resolvePath('bpmn-js', 'dist'),
            src: ['**/*.*', '!**/*.js'],
            dest: '<%= config.dist %>/vendor/bpmn-js'
          }
        ]
      },
      app: {
        files: [
          {
            expand: true,
            cwd: 'app/',
            src: ['**/*.*', '!**/*.js'],
            dest: '<%= config.dist %>/'

          },
          {
            expand: true,
            cwd: 'styles/',
            src: [
              'colorpicker-icon.svg',
              'line-type-picker-icon.svg',
              'line-type-clear-icon.svg',
              'line-type-dotted-icon.svg',
              'line-type-thick-icon.svg',
              'line-type-curved-icon.svg',
              'line-type-curved-thick-icon.svg',
              'label-size-picker-icon.svg',
              'label-size-clear-icon.svg',
              'label-size-8px-icon.svg',
              'label-size-16px-icon.svg',
              'label-size-24px-icon.svg',
              'label-style-picker-icon.svg',
              'label-style-clear-icon.svg',
              'label-style-italic-icon.svg',
              'label-style-bold-icon.svg',
              'label-style-italicBold-icon.svg',
              'route.svg',
              'route_with_hover_on.svg',
              'bpmn-js-token-simulation.css',
              'normalize.css'
            ],
            dest: '<%= config.dist %>/css/'

          }
        ]
      }
    },

    less: {
      options: {
        dumpLineNumbers: 'comments',
        paths: [
          'node_modules'
        ]
      },

      styles: {
        files: {
          '<%= config.dist %>/css/app.css': 'styles/app.less',
          '<%= config.dist %>/css/context-pads.css': 'styles/context-pads.less'

        }
      }
    },

    watch: {
      options: {
        livereload: 35730
      },

      samples: {
        files: [ 'app/**/*.*', 'styles/**/*.*' ],
        tasks: [ 'copy:app' ]
      },

      less: {
        files: [
          'styles/**/*.less',
          'node_modules/bpmn-js-properties-panel/styles/**/*.less'
        ],
        tasks: [
          'less'
        ]
      }


    },

    connect: {
      livereload: {
        options: {
          port: 9014,
          livereload: true,
          hostname: 'localhost',
          open: true,
          base: [
            '<%= config.dist %>'

          ]
        }
      }
    }
  });

  // tasks

  grunt.registerTask('build', [ 'copy', 'less', 'browserify:app' ]);

  grunt.registerTask('auto-build', [
    'copy',
    'less',
    'browserify:watch',
    'connect:livereload',
    'watch'
  ]);

  grunt.registerTask('default', [ 'build' ]);
};

Have you tried to delete the node_modules directory and the package-lock.json and run npm install again?

No, but I just did it and now the issue can be reproduced on my local environment too.

Okay, it seems I have the exact same problem but with browserify:

Right now I am resetting bpmn-js-properties-panel from 0.29.0(where this was introduced) to 0.28.2
But in the long term I have to fix this issue somehow.
To me it seems, the Ids package has been transformed to an ES module in version 1.0.0 and now bpmn-js-properties-panel(v0.29.0) is loading it as it is.
bpmn-js-properties-panel is a CommonJS module which I am loading in my ES module project.
Until Ids was not an ES module there was no issue with my config.

Do you have any more idea where to look for the problem?

How do you import the library?

I am using the property-panel like this:
import propertiesPanelModule from 'bpmn-js-properties-panel';
and depend on it like this:
"bpmn-js-properties-panel": "file:C:/repositories/bpmn-js-properties-panel",
Here this property-panel has some minor tweaks but those can’t be the problem.
However I had to add this line to its devDependencies because of a bug(https://github.com/bpmn-io/bpmn-js-examples/issues/42):
"babel-preset-env": "^1.7.0",

any luck with this? I have same issue with extending panel

As I wrote previously I was resetting bpmn-js-properties-panel from 0.29.0(where this issue was introduced) to 0.28.2 and it worked for me.
But in the long term I don’t have a solution.

yes, thanks, this worked for me
I was hoping you found maybe more permanent fix :slight_smile:

A late reply but here my solution for others who still have this problem. bpmn-js-properties-panel (at least up to version 0.32.0) seems to request a very old version of ids “^0.2.0” which uses es5 js and not es6 modules or commonjs. I tackled the problem by forcing ids to be version 1.0.0. If you use yarn you can force ids to be at version 1.0.0 by adding resolutions to the package.json:

  "resolutions": {
    "ids": "1.0.0"
  }

For npm you have to install a plugin like NPM Force Resolutions first before being able to use resolutions in package.json.
As far as i can tell there were no breaking changes from ids 0.2.0 to 1.0.0 and all is working fine for me.