skip to content

How does JMeter's CSV Data Set Config behave when it reaches the end of the file?

level: middleimportance: must knowfreq 78%

answer

  1. Two checkboxes decide the outcome
  2. Only read when the other is off
  3. A placeholder lands in every variable
  4. csvdataset.eofstring renames that placeholder

basics

~20 s

Two checkboxes decide. Recycle on EOF, ticked by default, reopens the file at line one. With Recycle off and Stop thread on EOF off, every variable becomes <EOF>. With Recycle off and Stop thread on, the thread stops.

solid answer

~40 s

JMeter 6.0.0's `CSV Data Set Config` has three end-of-file outcomes chosen by two checkboxes. `Recycle on EOF` is **ticked by default**: the reader is closed and reopened, so reading resumes at line 1 and rows are reused for ever. Untick it and `Stop thread on EOF` decides the rest. Left unticked, every variable the element declares is set to the literal string `<EOF>` and the thread keeps iterating, so samplers keep firing with `<EOF>` where the data should be. Ticked, the thread is stopped from the element's iteration-start hook, before any sampler in that iteration runs, so **no sample is recorded** for it. `Stop thread on EOF` has no effect at all while `Recycle on EOF` is still ticked. The sentinel string is the JMeter property `csvdataset.eofstring`, default `<EOF>`.

code

xml · 11 lines
xml
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="Logins" enabled="true">
  <stringProp name="filename">logins-10k.csv</stringProp>
  <stringProp name="fileEncoding"></stringProp>
  <stringProp name="variableNames">USER,PASS</stringProp>
  <boolProp name="ignoreFirstLine">false</boolProp>
  <stringProp name="delimiter">,</stringProp>
  <boolProp name="quotedData">false</boolProp>
  <boolProp name="recycle">false</boolProp>
  <boolProp name="stopThread">true</boolProp>
  <stringProp name="shareMode">shareMode.all</stringProp>
</CSVDataSet>

go deeper

for a junior

Recall that Recycle on EOF is on by default, so a short data file is reused rather than exhausted. Know the two checkboxes exist and that they change what happens at the last row.

for a middle

Explain all three outcomes and the dependency between the boxes: Stop thread on EOF is only consulted once Recycle on EOF is unticked. Name the <EOF> sentinel and the property behind it.

for a senior

Show what each outcome looks like in a real run: reused credentials, a tail of <EOF> requests, or a run that ends early with no recorded failure. Say which you would choose for a one-row-per-thread file and why.

for a principal

Own the convention for plans in your organisation: whether exhausting the data set should end the run or be visible in results, and how that choice is made obvious to whoever reads the output later.

## Two checkboxes, three outcomes `Recycle on EOF` and `Stop thread on EOF` are the only two fields on JMeter's **CSV Data Set Config** that decide what happens when a thread asks for a row and there is none left. In JMeter 6.0.0 the defaults are **Recycle on EOF ticked** and **Stop thread on EOF unticked**. | Recycle on EOF | Stop thread on EOF | What happens at the last row | |---|---|---| | ticked (the default) | either | the reader is closed and reopened; reading resumes at line 1 | | unticked | unticked | every declared variable is set to `<EOF>` and the thread keeps iterating | | unticked | ticked | that thread is stopped | ## Why Stop thread on EOF is dead while Recycle is on With `Recycle on EOF` ticked, JMeter reopens the file the moment a read comes back empty, so the end-of-file branch is never reached and the `Stop thread on EOF` checkbox has no effect at all. JMeter's own tooltip states the dependency: *Stop the thread on reaching EOF (if Recycle is false)*. A plan with both boxes ticked is not a belt-and-braces configuration — it is a plan that will recycle for ever. ## The `<EOF>` sentinel The middle row of the table is the quiet one. When the file runs out and neither box asks for anything else, every variable the element declares is set to the literal string `<EOF>`: - the sampler still fires, with `<EOF>` where the credential should be; - the result is usually a well-formed rejection from the server, not a JMeter error; - nothing in the element's own behaviour marks the transition, so a 10,000-row credential file backing a longer run produces real logins followed by a tail of identical `<EOF>` attempts. The string comes from the JMeter property `csvdataset.eofstring`, which ships commented out in `bin/jmeter.properties` with a default of `<EOF>`. It is read once when the class is loaded, so set it in a properties file before the run starts; changing it mid-run has no effect. ## What "stop thread" actually does The stop path throws a `JMeterStopThreadException` from the element's iteration-start hook — that is, **before any sampler in that iteration runs**. JMeter catches it, logs a line naming the thread and the file, and ends that one thread; other threads continue until they hit the same wall. Because the exception fires ahead of the samplers, **no sample is recorded for the aborted iteration**: a run configured this way finishes early and quietly rather than producing a burst of failures. ## Where end of file is actually reached The element reads one row at the **start of each iteration**, so the end of the file is hit by an iteration, not by a sampler. Three consequences follow: - `Filename` and `Sharing mode` are resolved on the first iteration and the file is opened once; the two checkboxes are then consulted on every read after that. - Recycling is a **close and reopen**, not a seek backwards. If the element takes its names from a header line, that line is skipped again on every reopen, so a recycled pass never hands a thread the header row. - Which threads hit the end together depends on `Sharing mode`. On the default `All threads` the 10,000 rows are exhausted once across every thread combined; set to `Current thread`, each thread has its own reader and exhausts it separately, so the stop or the `<EOF>` tail arrives at a different moment per thread. ## Wiring the 10,000-row login file so each row is used once 1. Put the file in `Filename` and either type `USER,PASS` into `Variable Names` or leave that field empty and let the header name the columns. 2. **Untick `Recycle on EOF`.** Leave it ticked and the fastest thread will be back on row 1 while a slower one is still on row 40, so rows get reused long before the file is exhausted. 3. Tick `Stop thread on EOF` if running out of credentials should end the thread, or leave it unticked if you would rather the run continue and show you the `<EOF>` tail. 4. Leave `Sharing mode` on `All threads` so the 10,000 rows are handed out from one pointer across every thread. 5. Expect the run to end early when the threads exhaust the file — with `Stop thread on EOF` ticked that is the designed outcome, not a failure to diagnose.

  • With Recycle on EOF and Stop thread on EOF both off, what does the sampler actually send?
    The literal text <EOF> in place of each variable the element declares. Requests keep firing with that value, so a credential-driven plan produces a tail of identical rejected logins rather than stopping. Nothing in the element flags the transition.
  • Which JMeter property changes the string written at end of file, and when is it read?
    csvdataset.eofstring, which ships commented out in bin/jmeter.properties with a default of <EOF>. It is read once when the class loads, so it has to be set in a properties file before the run starts.
  • Why does a run configured to stop threads at EOF often show no failures at all?
    The stop is raised from the element's iteration-start hook, before any sampler in that iteration executes, so JMeter records no sample for the aborted iteration. The run simply ends earlier than the schedule you configured.

saying these in an interview costs you the question

  • Says the whole run stops when the CSV file runs out, whatever the settings.
  • Assumes Stop thread on EOF works while Recycle on EOF is still ticked.
  • Thinks reaching end of file produces a failed sample you would notice.
  • Believes recycling is off by default in the CSV Data Set Config.
  • Expects <EOF> to raise an error rather than be sent as a value.