Skip to content

JMeter JSR223 Groovy Script Errors & Exceptions

Fix JMeter JSR223 Groovy script errors: ScriptException, MissingPropertyException, null pointer errors, vars vs props scope, and compilation caching.

Difficulty
intermediate
Guide type
troubleshooting
Estimated read time
7 min read
Last verified version
Verified JMeter 5.6

When executing JSR223 Samplers, PreProcessors, PostProcessors, or Assertions, samples turn red or errors appear in jmeter.log:

2026-08-18 10:15:32,410 ERROR o.a.j.m.JSR223PostProcessor: Problem in JSR223 script, JSR223 PostProcessor
javax.script.ScriptException: groovy.lang.MissingPropertyException: No such property: token for class: Script1
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:324)

Or for null pointers when accessing variables:

java.lang.NullPointerException: Cannot invoke method split() on null object
at Script1.run(Script1.groovy:4)

The error causes the sampler to fail and logs a stack trace for every virtual user thread execution.

  • MissingPropertyException: You referenced an undeclared variable directly (e.g. println token) instead of accessing it via the JMeter variables object (vars.get("token")).
  • NullPointerException: vars.get("name") returned null because the variable was never created or an upstream extractor failed to find a match.
  • Compilation Cache Full / High CPU: Script text contains \${var} string interpolation instead of using vars.get("var").

Essential JSR223 Implicit Objects Reference

Section titled “Essential JSR223 Implicit Objects Reference”

JMeter automatically injects predefined context objects into Groovy scripts:

ObjectClassScope & Purpose
varsJMeterVariablesThread-scoped read/write (vars.get("k"), vars.put("k", "v"), vars.putObject("k", obj))
propsJMeterPropertiesGlobal cross-thread properties (props.get("p"), props.put("p", "v"))
prevSampleResultPrevious sampler result (prev.getResponseDataAsString(), prev.setSuccessful(false))
samplerSamplerCurrent sampler object (sampler.setName("New Name"))
ctxJMeterContextEngine context (ctx.getThreadNum(), ctx.getPreviousResult())
logLoggerLog4j2 logger (log.info("msg"), log.error("err", exception))

1. Always Use vars.get() and vars.put() (Never Direct Variables)

Section titled “1. Always Use vars.get() and vars.put() (Never Direct Variables)”

In Groovy, JMeter variables are not global script variables. Always access them via the vars object:

// ❌ WRONG: Throws MissingPropertyException if not declared in script
String myId = userId;
// ❌ WRONG: String interpolation breaks compilation caching and leaks Metaspace!
String myId = "${userId}";
// ✅ CORRECT: Safe retrieval with null checking
String myId = vars.get("userId");
if (myId != null) {
vars.put("processedUserId", myId.trim().toUpperCase());
} else {
log.warn("Variable 'userId' was null! Upstream extractor may have failed.");
}

If an upstream JSON Extractor or Regex Extractor fails, vars.get() returns null. Add safe navigation (?.) or explicit null guards:

// Using Groovy safe navigation operator
String rawResponse = prev?.getResponseDataAsString();
String authToken = vars.get("authToken");
if (!authToken) {
// Fail the sample deliberately with a clear error message
prev.setSuccessful(false);
prev.setResponseMessage("Missing required authToken from previous step");
prev.setResponseCode("500");
return;
}

3. Share Data Between Different Thread Groups with props

Section titled “3. Share Data Between Different Thread Groups with props”

vars are strictly isolated per thread. If Thread Group A extracts a token needed by Thread Group B, use props:

// In Thread Group A (Writer)
props.put("GLOBAL_AUTH_TOKEN", vars.get("authToken"));
// In Thread Group B (Reader)
String globalToken = props.get("GLOBAL_AUTH_TOKEN");
vars.put("localToken", globalToken);

In every JSR223 component:

  1. Ensure Language is set to groovy.
  2. Check Cache compiled script if available.
  3. Do not put dynamic values in the script body; use vars.get() or script Parameters:
    • Parameters: \${__threadNum} \${userId}
    • Script access: String p0 = args[0];

5. Parse JSON and XML Safely with Groovy Builders

Section titled “5. Parse JSON and XML Safely with Groovy Builders”

Use built-in Groovy parsers instead of manual regex string manipulation:

import groovy.json.JsonSlurper
import groovy.json.JsonOutput
try {
def json = new JsonSlurper().parseText(prev.getResponseDataAsString())
String itemId = json.data.items[0].id
vars.put("firstItemId", itemId)
} catch (Exception e) {
log.error("Failed to parse JSON response: " + e.getMessage(), e)
prev.setSuccessful(false)
}
ResourceUse when
Metaspace & GC overheadFixing Metaspace leaks caused by Groovy scripts
Functions and variablesBuilt-in JMeter functions guide
Correlation & dynamic valuesExtracting and passing dynamic values
Best practicesScripting language performance recommendations

Should I use BeanShell or Groovy for scripting in JMeter?

Section titled “Should I use BeanShell or Groovy for scripting in JMeter?”

Always use Groovy (JSR223). Groovy compiles down to native Java bytecode and supports script compilation caching, making it 10x to 50x faster than BeanShell. BeanShell is deprecated for high-load testing.

Why do my changes to vars not appear in other threads?

Section titled “Why do my changes to vars not appear in other threads?”

vars (JMeterVariables) are local to the current thread. To pass data across threads, use props.put("key", value) and props.get("key").

On this page