Q23 of 40 · Karate
How would you debug a Karate scenario that fails with a confusing match error?
KarateMidkaratedebuggingmatchtroubleshootingapi-testing
Short answer
Short answer: Karate's match failure shows the actual vs expected diff with the exact path that failed. Add * print response to log the raw response before the match. Use match response contains rather than == to narrow which fields are wrong. The karate.log() function and * configure lowerCaseResponseHeaders = true help isolate header mismatches.
Detail
Step 1 — read the error message carefully: Karate's match failures show the path, actual value, and expected value:
path: $.name, actual: 'alice', expected: 'Alice'
Step 2 — print the raw response:
* print response
# or for a specific field:
* print 'name field is:', response.name
Step 3 — narrow with contains:
# Change == to contains to find which field fails
* match response contains { id: '#number' } # does id exist?
* match response contains { name: 'Alice' } # is name correct?
Step 4 — use karate.log():
* def debug = function() { karate.log('response body:', response); return true }
* call debug
Common causes of confusing match errors:
- Trailing whitespace in string values:
'Alice 'vs'Alice' - Integer vs String type: JSON field is
"42"(string) but you're matching42(number) - Nested path typo:
response.user.namevsresponse.users[0].name - Response is an array but you're matching as an object — check
* print response.getClass() - Header case: Karate lowercases header names; use
* configure lowerCaseResponseHeaders = trueto align
// EXAMPLE
debug-example.feature
Feature: Debugging a failing match
Scenario: Debug user response match failure
* url 'https://api.example.com'
Given path '/users/1'
When method GET
Then status 200
# Step 1: print the full response to understand the structure
* print 'Full response:', response
# Step 2: use contains to isolate the failing field
* match response contains { id: '#present' } # does id exist?
* match response contains { name: '#string' } # is name a string?
# Step 3: add type checks before value checks
* match response.id == '#number' # verify type first
* match response.name == '#string' # then type of name
* match response.name == 'Alice' # then exact value
# Step 4: check for whitespace issues
* def trimmedName = response.name.trim()
* match trimmedName == 'Alice'// WHAT INTERVIEWERS LOOK FOR
Using * print before the failing match, narrowing with contains to isolate the problem field, and knowing the common causes of confusing failures (type mismatch, whitespace, array vs object). Systematic debugging rather than random config changes.
// COMMON PITFALL
Immediately editing the expected value to match the actual value without understanding why they differ. A mis-returned type (string vs number) or trailing whitespace indicates a server bug — fix the server, not the test.