karate.set(callSingle()) + call read() in Background freezes Outline row values
#2,934 opened on Jun 19, 2026
Repository metrics
- Stars
- (7,600 stars)
- PR merge metrics
- (Avg merge 14h 17m) (25 merged PRs in 30d)
Description
Description
When a Scenario Outline Background uses karate.set(karate.callSingle('feature')) followed by call read('feature'), all Outline rows receive row 1's Examples column values. The scope is frozen after row 1 — subsequent rows don't get their own values applied to #() expressions in the request body.
Observation- karate.set(callSingle()) followed by any call read() (with or without HTTP call) in Background seems to be the trigger. Neither alone triggers the issue — it's the combination.
Impact- The scope freeze affects BOTH the #() expressions in request bodies AND the variable references in assertions. Tests may false-pass because both the sent data and the expected values are frozen to row 1's values (Alice == Alice passes for all rows). The reproduction uses __num to reliably detect the freeze.
Steps to Reproduce
- Create a feature file using the snippets below.
Feature: karate.set(callSingle()) + call read() in Background freezes Outline row values
Background:
* karate.set( karate.callSingle('classpath:v2MigrationBugs/callSingleSetOutlineRows/constants.feature') )
* def bgResult = call read('classpath:v2MigrationBugs/callSingleSetOutlineRows/bgNoHttpCall.feature')
* def existingItems = bgResult.items || []
Scenario Outline: Row <rowNum> - each row must have its own phoneNumber
* def expectedPhones = ['1111111111', '2222222222', '3333333333', '4444444444']
* def expectedPhone = expectedPhones[__num]
# This assertion WILL FAIL on rows 2-4 if scope is frozen:
# phone will be '1111111111' (row 1's value) but expectedPhone will differ
* match phone == expectedPhone
Examples:
| fName! | lName! | phone! | active! | rowNum! |
| 'Alice' | 'Smith' | '1111111111' | true | 1 |
| 'Bob' | 'Jones' | '2222222222' | false | 2 |
| 'Charlie' | 'Brown' | '3333333333' | true | 3 |
| 'Diana' | 'Prince' | '4444444444' | false | 4 |
- Create a feature file using the snippets below for constants.feature being called in the above feature from callSingle
@ignore
Feature: Simulated Pre-req (callSingle-cached, returns object for karate.set)
Scenario:
* def serviceName = 'TestService'
* def baseUrl = 'https://httpbin.org'
* def domainPath = '/anything'
* def someFlag = true
* def headers = { 'Content-Type': 'application/json' }
- Create a feature file using the snippets below for
call read('feature')being called in the main feature's background.
@ignore
Feature: Background call WITHOUT HTTP (control test)
Scenario:
* def items = [{ id: 'item1' }, { id: 'item2' }]
Expected Behavior
- Each Scenario Outline row gets its own Examples column values. The Background re-executes for each row, and #(fName), #(lName), #(phone) in the request doc-string resolve to the current row's values. Each HTTP request contains distinct data.
Actual Behavior
- All rows receive row 1's values. The #() expressions in the doc-string resolve to row 1's column values for every subsequent row
Karate Version
2.1.0
Java Version
25.0.2
Operating System
macOS