"undefined is not a function" error when feeding my simulation with .json/.csv file

Gatling version: 3.13.2
Gatling flavor: javascript
Gatling build tool: maven gradle sbt bundle npm

My simulation works perfectly when retrieves only one key-value pair from .json/.csv file. But once I want to retrieve random value from .json/.csv file and add feeder - I receive error “undefined is not a function”.
My simulation with csv feeding:

import {
    simulation,
    scenario,
    pause,
    atOnceUsers,
    AllowList,
    DenyList,
    StringBody,
    jsonFeeder,
    feed,
    csv
} from "@gatling.io/core";
import {http, status} from "@gatling.io/http";

const credsFeeder = csv("../resources/creds.csv").random();

const httpProtocol = http
    .baseUrl("https://qa.myproject.co")
    .inferHtmlResources()
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36");

const headers_0 = {
    "Content-Type": "application/json",
    "Prefer": "timezone=Europe/Bratislava",
    "sec-ch-ua": "Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "macOS"
};

const scn = scenario("loginSF")
    .feed(credsFeeder)
    .exec(
        http("request_0")
            .post("/api/authentication/auth/sign_in")
            .headers(headers_0)
            .body(
                StringBody(`{
                    "login": "#{login}",
                    "password": "#{password}"
                }`)
            )
            .check(status().is(200)) // Check if the login is successful
    );

export default simulation((setUp) => {
    setUp(scn.injectOpen(atOnceUsers(10))).protocols(httpProtocol);
});

My creds.csv:

login,password
log1,pas1
log2,pas2

My simulation with json feeding:

import { simulation, scenario, atOnceUsers, jsonFeeder } from "@gatling.io/core";
import { http, status } from "@gatling.io/http";

const httpProtocol = http
    .baseUrl("https://qa.myproject.co")
    .inferHtmlResources()
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36");

const headers_0 = {
    "Content-Type": "application/json",
    "Prefer": "timezone=Europe/Bratislava",
    "sec-ch-ua": "Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "macOS",
};

const credsFeeder = jsonFeeder("../resources/creds.json").random();

const scn = scenario("loginSF")
    .feed(credsFeeder)  
    .exec(
        http("request_0")
            .post("/api/authentication/auth/sign_in")
            .headers(headers_0)
            .body((session) => {
                // Dynamically retrieve the login and password from the session
                const login = session.get("login");
                const password = session.get("password");
                return JSON.stringify({
                    login: login,   
                    password: password  
                });
            })
            .check(status().is(200))  
    );

export default simulation((setUp) => {
    setUp(scn.injectOpen(atOnceUsers(100))).protocols(httpProtocol);
});

My creds.json:

[
    {
        "login": "log1",
        "password": "pass1"
    },

    {
        "login": "log1",
        "password": "pass1"
    }
]

Both options work fine when there is only one key-value pair in .csv file/.json file

Full error log:

Run crashed
org.graalvm.polyglot.PolyglotException: TypeError: undefined is not a function
	at <js>.:=>(bundle.js:2893)
	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$Java.params(SimulationClass.scala:47)
	at io.gatling.app.Runner.load(Runner.scala:73)
	at io.gatling.app.Runner.run(Runner.scala:58)
	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$Java.params(SimulationClass.scala:47)
	at io.gatling.app.Runner.load(Runner.scala:73)
	at io.gatling.app.Runner.run(Runner.scala:58)
	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:2893)
	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
/Users/anna/Documents/gatling-js/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> (/Users/anna/Documents/gatling-js/javascript/node_modules/@gatling.io/cli/target/java.js:33:24)
    at ChildProcess.emit (node:events:513:28)
    at maybeClose (node:internal/child_process:1101:16)
    at ChildProcess._handle.onexit (node:internal/child_process:305:5)

I’ve fixed an import error in your CSV sample.

Then:

  • jsonFeeder("../resources/creds.json") is wrong. You must use paths contained in the resources folder, meaning directly jsonFeeder("creds.json") in this case.
  • the qa.structuretest.co can’t be resolved, I guess it’s an internal one. Please build a test that can be run by someone outside your organization, eg targeting https://httpbin.org/.

Thanks, @slandelle. But it is not about path, initially I used exactly “creds.json” path, and rechecked now too - same error

Please build a proper reproducer I can run on my side. I only bothered running your CSV sample with the import and path fixes and hitting google.com instead and it worked (100% 404 as expected, but Gatling was able to build the request bodies).

strange, I’ve just changed baseUrl to “https://google.com” and still see same error, Gatling is not able to build the request bodies:

import { simulation, scenario, atOnceUsers, jsonFeeder } from "@gatling.io/core";
import { http, status } from "@gatling.io/http";

const httpProtocol = http
    .baseUrl("https://google.com")
    .inferHtmlResources()
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36");

const headers_0 = {
  "Content-Type": "application/json",
  "Prefer": "timezone=Europe/Bratislava",
  "sec-ch-ua": "Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24",
  "sec-ch-ua-mobile": "?0",
  "sec-ch-ua-platform": "macOS",
};

const credsFeeder = jsonFeeder("creds.json").random();

const scn = scenario("loginSF")
    .feed(credsFeeder)
    .exec(
        http("request_0")
            .post("/api/authentication/auth/sign_in")
            .headers(headers_0)
            .body((session) => {
              // Dynamically retrieve the login and password from the session
              const login = session.get("login");
              const password = session.get("password");
              return JSON.stringify({
                login: login,
                password: password
              });
            })
            .check(status().is(200))
    );

export default simulation((setUp) => {
  setUp(scn.injectOpen(atOnceUsers(100))).protocols(httpProtocol);
});

Your CSV sample was almost correct, except for the missing import and the path.

Your JSON sample has way more errors:

  • you must pass a StringBody (or another “Body” type) to body() => StringBody(your function)
  • it’s not jsonFeeder but jsonFile, see Gatling session scripting reference - feeders
  • missing imports for StringBody, feed, jsonFile

I’m not a JavaScript developper, but I would expect all these errors to be better reported when using TypeScript.

Thanks a lot @slandelle, it was perfect idea to use TypeScript. I modified just a bit my scripts and both scripts, using .json and .csv feeding, work perfectly. But when I run exactly the same 100% identical script with .csv feeding using JS, I still see this “undefined is not a function” error. So, apparently issue is not on my side in this case. So, it is just better to use TS, thanks!

No, really, your script is buggy.

Here’s the corrected version with the fixes I provided:

import { simulation, scenario, atOnceUsers, StringBody, feed, jsonFile } from "@gatling.io/core";
import { http, status } from "@gatling.io/http";

const credsFeeder = jsonFile("creds.json").random();

const httpProtocol = http
    .baseUrl("https://google.com")
    .inferHtmlResources()
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36");

const headers_0 = {
  "Content-Type": "application/json",
  "Prefer": "timezone=Europe/Bratislava",
  "sec-ch-ua": "Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24",
  "sec-ch-ua-mobile": "?0",
  "sec-ch-ua-platform": "macOS",
};

const scn = scenario("loginSF")
    .feed(credsFeeder)
    .exec(
        http("request_0")
            .post("/api/authentication/auth/sign_in")
            .headers(headers_0)
            .body(
                StringBody(
                    (session) => {
                        // Dynamically retrieve the login and password from the session
                        const login = session.get("login");
                        const password = session.get("password");
                        return JSON.stringify({
                            login: login,
                            password: password
                        });
                    }
                )
            )
            .check(status().is(200))
    );

export default simulation((setUp) => {
  setUp(scn.injectOpen(atOnceUsers(100))).protocols(httpProtocol);
});
---- Global Information --------------------------------------------------------
> request count                                        100 (OK=0      KO=100   )
> min response time                                    171 (OK=-      KO=171   )
> max response time                                    296 (OK=-      KO=296   )
> mean response time                                   227 (OK=-      KO=227   )
> std deviation                                         30 (OK=-      KO=30    )
> response time 50th percentile                        224 (OK=-      KO=224   )
> response time 75th percentile                        252 (OK=-      KO=252   )
> response time 95th percentile                        266 (OK=-      KO=266   )
> response time 99th percentile                        296 (OK=-      KO=296   )
> mean requests/sec                                    100 (OK=-      KO=100   )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms                                             0 (     0%)
> 800 ms <= t < 1200 ms                                  0 (     0%)
> t >= 1200 ms                                           0 (     0%)
> failed                                               100 (   100%)
---- Errors --------------------------------------------------------------------
> status.find.is(200), but actually found 404                       100 (100,0%)
================================================================================

ok) but my version also works:

import {
    simulation,
    scenario,
    csvFeeder,
    atOnceUsers,
    exec,
    csv,
    pause,
    css,
    feed,
    repeat,
    tryMax,
    rampUsers,
    StringBody,
    jsonFeeder,
    jsonFile
} from "@gatling.io/core";
import { http, status } from "@gatling.io/http";

const httpProtocol = http
    .baseUrl("https://google.com")
    .inferHtmlResources()
    .userAgentHeader(
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
    );

const headers_0 = {
    "Content-Type": "application/json",
    "Prefer": "timezone=Europe/Bratislava",
    "sec-ch-ua": 'Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "macOS",
};

const credsFeeder = jsonFile("resources/creds.json").random();

const scn = scenario("RecordedSimulation")
    .feed(credsFeeder)
    .exec(
        http("request_0")
            .post("/api/authentication/auth/sign_in")
            .headers(headers_0)
            .body(
                StringBody('{"login": "#{login}", "password": "#{password}"}')
            )
            .check(status().is(200))
    );

export default simulation((setUp) => {
    setUp(scn.injectOpen(atOnceUsers(100))).protocols(httpProtocol);
});
================================================================================
---- Global Information --------------------------------------------------------
> request count                                        100 (OK=100    KO=0     )
> min response time                                   2267 (OK=2267   KO=-     )
> max response time                                  10143 (OK=10143  KO=-     )
> mean response time                                  7872 (OK=7872   KO=-     )
> std deviation                                       2001 (OK=2001   KO=-     )
> response time 50th percentile                       8438 (OK=8438   KO=-     )
> response time 75th percentile                       9653 (OK=9653   KO=-     )
> response time 95th percentile                      10003 (OK=10003  KO=-     )
> response time 99th percentile                      10143 (OK=10143  KO=-     )
> mean requests/sec                                   9.09 (OK=9.09   KO=-     )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms                                             0 (     0%)
> 800 ms <= t < 1200 ms                                  0 (     0%)
> t >= 1200 ms                                         100 (   100%)
> failed                                                 0 (     0%)
================================================================================

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.