In JMeter, what does the jmeterengine.stopfail.system.exit property actually control?
answer
- Read the property name's first word carefully
- It fires during shutdown, not during sampling
- Which request had already been made?
- Its two siblings both force a zero exit
basics
~10 sThe property decides whether a non-GUI JMeter calls System.exit(1) after an explicit stop-now request leaves threads still running. Its default is true. It says nothing about whether any sample passed.
solid answer
~40 sIt is a **stuck-JVM** switch, not a pass/fail switch. On the stop-now path `StandardJMeterEngine` tells the thread groups to stop, waits, then calls `verifyThreadsStopped()`; each thread gets a `join` of `jmeterengine.threadstop.wait` milliseconds, 5000 by default. If threads are still alive and the run is non-GUI, JMeter logs `One or more test threads won't exit; see log file.` and, when `jmeterengine.stopfail.system.exit` is on, logs `Exiting`, prints `Fatal error, could not stop test, exiting` and calls `System.exit(1)`. Turn it off and JMeter prints `Fatal error, could not stop test` and leaves the JVM alive for you to kill. `StandardJMeterEngine` reads the default as `true`, and `bin/jmeter.properties` documents it as `true`. Nothing on this path looks at an error rate.
code
properties · 8 lines# bin/jmeter.properties (shipped values, all three commented out)
# Whether to call System.exit(1) on failure to stop threads in non-GUI mode.
# This only takes effect if the test was explicitly requested to stop.
#jmeterengine.stopfail.system.exit=true
#jmeterengine.force.system.exit=false
#jmeterengine.remote.system.exit=false
# Number of milliseconds to wait for a thread to stop
#jmeterengine.threadstop.wait=5000go deeper
Learn to read the name as 'stopping failed', not 'the test failed'. Setting it will never make a run with bad responses come back with a failing status.
Walk the conditions: a stop-now request, threads still alive after the join timeout, a non-GUI run, and the property on. Then say that none of them examines a sample.
Separate the two concerns in a pipeline: this property plus a job timeout covers a wedged injector, while a JTL-reading step covers a failed test. Explain why one cannot stand in for the other.
Own the convention that no JMeter property is treated as a quality gate anywhere in the estate, and that engine tuning keys and verdict rules stay in visibly different places.
## Why this property gets mistaken for a gate Its name reads like *exit the system on failure*, so teams that want a load stage to go red find it first, set it to `true`, and are surprised when a run at 100% errors still exits `0`. The word **stopfail** does not mean "the test failed"; it means **the stop failed** — JMeter asked its own threads to die and they did not. ## Exactly when it fires The call sits in `StandardJMeterEngine`'s stop task, and every one of these has to be true before it can run: 1. **The test was explicitly told to stop now**, not merely allowed to finish. The task's `now` flag distinguishes a stop-now from an orderly shutdown; the orderly branch only calls `stopAllThreadGroups()` and never reaches this code. 2. **The threads did not stop.** `verifyThreadsStopped()` walks every thread group and `join`s each live thread for `jmeterengine.threadstop.wait` milliseconds — 5000 by default. Only if a thread is still alive after that does the branch fail. 3. **The run is non-GUI.** `JMeter.isNonGUI()` gates it; in the GUI you get an error dialog instead. 4. **The property is on**, which it is unless you set it off, because the engine reads it with a default of `true`. Then, and only then: `log.error("Exiting")`, `Fatal error, could not stop test, exiting` on stdout, and `System.exit(1)`. Notice what is absent from that list — any reference to a sample, an assertion, an error rate or the results file. ## The three exit properties, side by side | Property | Default | What it does | |---|---|---| | `jmeterengine.stopfail.system.exit` | `true` | `System.exit(1)` when a stop-now request leaves threads alive in CLI mode | | `jmeterengine.force.system.exit` | `false` | `System.exit(0)` at the end of a CLI test even with no failures, for a JVM that will not exit on its own | | `jmeterengine.remote.system.exit` | `false` | `System.exit(0)` in the server after RMI has been stopped | Two of the three force a **zero** exit. None of them can produce a non-zero code from a test result. That table is the honest answer to "which JMeter property fails my build?" — there isn't one. ## A documentation wrinkle worth knowing The shipped `bin/jmeter.properties` and the properties reference both document the default as `true`, and `StandardJMeterEngine` reads it that way. One page of the user manual, the CLI-mode section of the getting-started document, still says the default is `false`. The code and the properties file agree; if you need to be sure in your own build, print the effective value rather than trusting a prose page. ## What to do instead If you want a stuck JMeter to be visible in CI, leave this property alone at `true` and put a wall-clock timeout on the job — the property only helps once the engine has *tried* to stop, and a run that is merely slow never triggers it. If you want a failed *test* to be visible, none of these properties help: add a step after JMeter that reads the `success` column of the JTL and exits non-zero itself. Those are two separate concerns and they need two separate mechanisms.
- You set jmeterengine.stopfail.system.exit=false. What changes in a CLI run?Only the failure path. When a stop-now request leaves threads alive, JMeter prints 'Fatal error, could not stop test' and returns instead of calling System.exit(1), so the JVM may sit there holding the job until something kills it externally. Nothing about a normal run changes.
- Does jmeterengine.force.system.exit help a build detect a failed run?No. It forces System.exit(0) at the end of a CLI test, and exists so a JVM kept alive by a stray non-daemon thread still terminates. It makes the run end, always with a zero status, which is the opposite of a gate.
saying these in an interview costs you the question
- Reads stopfail as 'the test failed' rather than 'stopping failed'
- Sets it to true expecting failed samples to exit non-zero
- Thinks it applies to an orderly end-of-test shutdown
- Confuses it with jmeterengine.force.system.exit, which exits zero
- Believes it works in GUI runs as well as non-GUI ones