karatelabs/karate · error · DriverException
WebDriver session create response missing sessionId: " +…
Error message
WebDriver session create response missing sessionId: " + response.body()
What it means
After a 200 response, W3cSession.create parses the JSON body and throws DriverException if the `value.sessionId` field is absent, including the raw body in the message. A 200 without a sessionId is a malformed/unexpected response from whatever answered the WebDriver port.
Solutions
- Verify the host/port points at the real WebDriver endpoint (curl /status and inspect the response)
- Inspect the echoed body in the message to see what actually replied
- Use a W3C-compliant driver version (legacy JSON-wire drivers put sessionId outside value)
- Bypass proxies for localhost so the request reaches the driver directly
Example fix
// before
driver('type', 'chromedriver', 'port', 9222); // 9222 is DevTools, not chromedriver
// after
driver('type', 'chromedriver', 'port', 9515); // default chromedriver port Defensive patterns
Strategy: validation
Validate before calling
// confirm the endpoint really is WebDriver before session create
// GET /status must return 200 with { value: { ready: true, ... } } Type guard
boolean isW3cSessionBody(Map<String, Object> body) {
return body.get("value") instanceof Map<?,?> v && v.get("sessionId") instanceof String;
} Try / catch
try {
session = W3cSession.create(client, baseUrl, caps, timeout);
} catch (DriverException e) {
if (e.getMessage().contains("missing sessionId")) {
// inspect echoed body; fix host/port or driver protocol version
}
} Prevention
- Never point the driver at a DevTools (CDP) port expecting WebDriver semantics
- Bypass proxies for localhost driver traffic
- Use W3C-compliant driver versions
When it happens
Trigger: POST /session returns HTTP 200 but the body lacks value.sessionId — e.g. an intermediate proxy answered, the endpoint is not actually a WebDriver server, or a non-W3C (legacy JSON wire) driver returned a different body shape.
Common situations: Pointing the driver at the wrong port (another HTTP service listening there); corporate proxy intercepting the request; using an old driver that returns sessionId at the top level (pre-W3C protocol).
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- WebDriver session create failed with status " +…
- WebDriver session create failed: " + e.getMessage()
- WebDriver response missing element ID: " + elementMap
- session is unavailable: no sessionStore is configured. Call…
- session is unavailable: no sessionStore is configured. Call…
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/a5ae82b25622b45a.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/w3c/W3cSession.java:120
requestBuilder.header("Authorization", basicAuth);
}
HttpRequest request = requestBuilder
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new DriverException("WebDriver session create failed with status "
+ response.statusCode() + ": " + response.body());
}
Map<String, Object> body = Json.of(response.body()).asMap();
Map<String, Object> value = (Map<String, Object>) body.get("value");
String sessionId = (String) value.get("sessionId");
if (sessionId == null) {
throw new DriverException("WebDriver session create response missing sessionId: " + response.body());
}
logger.info("W3C session created: {}", sessionId);
return new W3cSession(client, baseUrl, sessionId, timeout);
} catch (IOException | InterruptedException e) {
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
throw new DriverException("WebDriver session create failed: " + e.getMessage(), e);
}
}
// ========== Navigation ==========
public void navigateTo(String url) {
post("url", Map.of("url", url));
}
View on GitHub (pinned to a22eb90246)