Got TypeError: undefined is not a function with Gatling-js

Gatling version: 3.13.401
Gatling flavor: javascript
Gatling build tool: npm

Hello, I’m learning on gatling-js for team need, with this sample script

// required for Gatling core structure DSL
import { scenario, simulation, ElFileBody, exec, atOnceUsers } from "@gatling.io/core";

// required for Gatling HTTP DSL
import { http, status } from "@gatling.io/http";

export default simulation((setUp) => {
    const ClientBulkReportingHigh = exec(
        http('ClientBulkReportingHigh')
            .post('URL')
            .header('Content-Type', 'application/json')
            .body(ElFileBody('jsonFile.json'))
            .check(status().is(200))
            .requestTimeout(300000) 
    );
    const UserBehavior = scenario('Users')
            .exec(ClientBulkReportingHigh);
    setUp(
            UserBehavior
                .injectOpen(atOnceUsers(1)),
        );
});

I got this error, while the computerdatabase simulation doesn’t get it:

Bundling a Gatling simulation with options:
 - sourcesFolder: src
 - bundleFile: target/bundle.js
 - typescript: false
Running a Gatling simulation with options:
 - simulation: ClientBulkReportingSimulation
 - bundleFile: target/bundle.js
 - resourcesFolder: resources
 - resultsFolder: target/gatling
15:30:30.134 [ERROR] i.g.a.Gatling$ - Run crashed
org.graalvm.polyglot.PolyglotException: TypeError: undefined is not a function
        at <js>.:=>(bundle.js:2892)
        at <js>.:program(bundle.js:1)
        at org.graalvm.polyglot.Context.eval(Context.java:402)
        at io.gatling.js.JsSimulationHelper.loadSimulation(JsSimulationHelper.java:64)
        at io.gatling.js.JsSimulation.<init>(JsSimulation.java:38)
        at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
        ... 9 common frames omitted
Wrapped by: java.lang.reflect.InvocationTargetException: null
        at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:74)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:501)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:485)
        at io.gatling.app.SimulationClass$JavaScript.params(SimulationClass.scala:57)
        at io.gatling.app.Runner.load(Runner.scala:72)
        at io.gatling.app.Runner.run(Runner.scala:55)
        at io.gatling.app.Gatling$.start(Gatling.scala:83)
        at io.gatling.app.Gatling$.fromArgs(Gatling.scala:46)
        at io.gatling.app.Gatling$.main(Gatling.scala:40)
        at io.gatling.app.Gatling.main(Gatling.scala)
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:74)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:501)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:485)
        at io.gatling.app.SimulationClass$JavaScript.params(SimulationClass.scala:57)
        at io.gatling.app.Runner.load(Runner.scala:72)
        at io.gatling.app.Runner.run(Runner.scala:55)
        at io.gatling.app.Gatling$.start(Gatling.scala:83)
        at io.gatling.app.Gatling$.fromArgs(Gatling.scala:46)
        at io.gatling.app.Gatling$.main(Gatling.scala:40)
        at io.gatling.app.Gatling.main(Gatling.scala)
Caused by: org.graalvm.polyglot.PolyglotException: TypeError: undefined is not a function
        at <js>.:=>(bundle.js:2892)
        at <js>.:program(bundle.js:1)
        at org.graalvm.polyglot.Context.eval(Context.java:402)
        at io.gatling.js.JsSimulationHelper.loadSimulation(JsSimulationHelper.java:64)
        at io.gatling.js.JsSimulation.<init>(JsSimulation.java:38)
        at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
        ... 9 more
C:\projects\gatling-js-demo-main\javascript\node_modules\@gatling.io\cli\target\java.js:33
                reject(Error("Gatling process finished with code " + code));
                       ^

Error: Gatling process finished with code 1
    at ChildProcess.<anonymous> (C:\projects\gatling-js-demo-main\javascript\node_modules\@gatling.io\cli\target\java.js:33:24)
    at ChildProcess.emit (node:events:524:28)
    at maybeClose (node:internal/child_process:1101:16)
    at ChildProcess._handle.onexit (node:internal/child_process:304:5)

Node.js v22.13.1

The log was not “friendly” to me to understand what exactly happened here, it would be helpful if I can get some insights, thank you.

Edit: My project source tree:

resources
   ->jsonFile.json
src
   ->ClientBulkReportSimulation.gatling.js

Other leave as default.

Hello, tried your code and it worked. However, I’m seeing the simulation that was run is named demoL, expecting it be inside a file called demoL.gatling.js, while the file you showed is named ClientBulkReportSimulation.gatling.js. Is it the same file that you used?

Hi @notdryft , just updated the log on original post, the command I was using:

npx gatling run --simulation ClientBulkReportingSimulation

Ok, same file then! Can I see the content of your package.json file?

here it is:

{
  "name": "gatling-js-demo",
  "version": "3.13.401",
  "private": true,
  "type": "module",
  "main": "target/bundle",
  "dependencies": {
    "@gatling.io/core": "3.13.401",
    "@gatling.io/http": "3.13.401"
  },
  "devDependencies": {
    "@eslint/js": "^9.21.0",
    "@gatling.io/cli": "3.13.401",
    "eslint": "^9.21.0",
    "globals": "^16.0.0",
    "prettier": "3.5.2",
    "rimraf": "6.0.1"
  },
  "scripts": {
    "clean": "rimraf target",
    "format": "prettier --write \"**/*.js\"",
    "build": "gatling build",
    "recorder": "gatling recorder",
    "computerdatabase": "gatling run --simulation computerdatabase"
  }
}

Still works for me, what version of node are you using?

Node version is v22.13.1

I just noticed that in the IDE the status() is marked as deprecated, I have to quit IDE and delete the 2nd import statement, then paste in the same import line again.
Test can be run now

You mean the status from import { http, status } from "@gatling.io/http"; ? I would expect something was replacing/considering it as the status from the browsers’ API instead of ours. Does that mean you were running the test with the IDE and not the npx gatling run command?

You mean the status from `import { http, status } from “@gatling.io/http”;

Yes this is what I deleted and paste again, the status() was marked in the check block

Does that mean you were running the test with the IDE and not the npx gatling run command?

Nope, I use Gatling’s guide command, npx gatling run

I guess during the installation of eslint, something was messed up.

Weird then… Also, looking at the devDependencies:

  "devDependencies": {
    "@eslint/js": "^9.21.0",
    "@gatling.io/cli": "3.13.401",
    "eslint": "^9.21.0",
    "globals": "^16.0.0",
    "prettier": "3.5.2",
    "rimraf": "6.0.1"
  },

Was it the IDE that prompted you to install globals? Both eslint imports and globals are not required and it didn’t change anything on my end having them but who knows…

IDE did not prompt me anything in installing, only eslint prompted during installation.
Moreover I was using VSCode for this.

Just a small other question:

import { scenario, simulation, ElFileBody, exec, atOnceUsers } from "@gatling.io/core";

I think this type of import forcing people to manually check back and forth for what they are using, I was running into errors for not declaring ElFileBody, exec, atOnceUsers on that import. Is there any way to improve this or is this an aspect of Javascript ?

Yes, it is a JavaScript particularity as you can’t import “*” (like Java/Scala) without putting inside a “scope”/namespace/variable, like this:

import * as core from "@gatling.io/core";
import * as http from "@gatling.io/http";

export default core.simulation((setUp) => {
  const ClientBulkReportingHigh = core.exec(
    http.http('ClientBulkReportingHigh')
      .post('URL')
      .header('Content-Type', 'application/json')
      .body(core.ElFileBody('jsonFile.json'))
      .check(http.status().is(200))
      .requestTimeout(300000)
  );
  const UserBehavior = core.scenario('Users')
    .exec(ClientBulkReportingHigh);
  setUp(
    UserBehavior
      .injectOpen(core.atOnceUsers(1)),
  );
});

We could have globals defined so you don’t have to import anything yourself but it could lead to issues with existing browser globals and our owns (when defined in multiple packages).

1 Like

got it, thanks for helping me, I think this little note should be updated on document site.