karatelabs/karate · warning
failed to create blank tab, quitting driver
Error message
failed to create blank tab, quitting driver
What it means
During close(), the driver first switches to a newly created blank tab (Target.createTarget with about:blank) so remaining pages can be torn down safely. If createTarget returns no targetId, the driver logs this warning and falls back to quit() — killing the whole browser instead of the graceful per-tab close. This means graceful close degraded to a hard shutdown.
Solutions
- Nothing to fix if the browser is already gone — quit() is the correct fallback; check earlier logs for the root cause of the browser death.
- Avoid double-close: guard with driver.isTerminated() or ensure quit() is called only once in teardown.
- If the browser crashes often, check for OOM in CI, mismatched browser/Driver versions, or a corrupted user-data-dir.
- Update Chrome/Chromium to a version compatible with the Karate release.
Example fix
// before
@After public void teardown() { driver.close(); driver.quit(); }
// after
@After public void teardown() { if (!driver.isTerminated()) { driver.quit(); } } Defensive patterns
Strategy: fallback
Validate before calling
if (driver.isTerminated()) { return; } // skip teardown if already dead Try / catch
try {
driver.close();
} catch (RuntimeException e) {
// close() itself falls back to quit(); swallow secondary teardown errors
logger.warn("teardown issue ignored: {}", e.getMessage());
} Prevention
- Call quit() exactly once in teardown; guard with isTerminated()
- Watch earlier logs for browser crashes (OOM, killed process)
- Keep browser and Karate versions compatible
- Avoid external process kills racing the driver's close path
When it happens
Trigger: close() called while the browser process is dying/crashed, CDP browser-level websocket already broken, or a browser build/version where Target.createTarget fails (e.g. too many targets, profile locked).
Common situations: Calling driver.quit()/close() twice, browser crashed earlier in the test, killing the browser externally (taskkill/OOM) before close(), or Chromium builds with restrictive target limits.
Related errors
- browser did not return a targetId for context
- timeout waiting for target to be removed
- CDP connection failed readiness check
- CDP timeout for
- CDP error
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/a690fe37b9ef851a.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:2758
String nextTarget = null;
for (String pageId : allPages) {
if (!pageId.equals(targetToClose)) {
nextTarget = pageId;
break;
}
}
logger.debug("close() - switching to: {}", nextTarget);
if (nextTarget == null) {
// Last tab - create a blank page to keep browser alive
// Uses browserMethod() because Target.createTarget is browser-level
CdpResponse response = cdp.browserMethod("Target.createTarget")
.param("url", "about:blank")
.send();
nextTarget = response.getResult("targetId");
logger.debug("close() - created blank tab: {}", nextTarget);
if (nextTarget == null) {
logger.warn("failed to create blank tab, quitting driver");
quit();
return;
}
}
// Switch to another tab first (establishes new session)
activateTarget(nextTarget);
logger.debug("close() - switched to: {}, now closing: {}", nextTarget, targetToClose);
// Register the removal future BEFORE sending closeTarget, then close.
// Target.closeTarget returns before the target is fully removed, so callers
// that enumerate tabs right after close() would still see the old one.
CompletableFuture<Void> removed = new CompletableFuture<>();
pendingTargetRemovals.put(targetToClose, removed);
try {
cdp.browserMethod("Target.closeTarget")
.param("targetId", targetToClose)
.send();View on GitHub (pinned to a22eb90246)