karatelabs/karate · warning
hook failed
Error message
{} hook failed: {} What it means
Karate runs lifecycle hooks (e.g. scenario setup/teardown callables) and, if a hook throws an Exception, logs this warning with the hook name and message and returns the exception to the caller instead of propagating it. The scenario continues unless the caller decides otherwise.
Solutions
- Read the hookName and message in the log to locate the failing hook
- Null-check any config/variables the hook reads
- Wrap risky parts of the hook body in try/catch inside the hook itself
- Run the hook's logic as a normal feature first to reproduce the error
Example fix
// before
configure afterScenario = function(){ karate.call('classpath:cleanup.feature') }
// after
configure afterScenario = function(){ try { karate.call('classpath:cleanup.feature') } catch(e){ karate.log('cleanup failed', e) } } Defensive patterns
Strategy: try-catch
Validate before calling
// Validate hook dependencies at config time:
if (!karate.get('cleanupUrl')) { throw new Error('cleanupUrl missing; hook would fail'); } Try / catch
try { callable.call(null); } catch (Exception e) { logger.warn("{} hook failed: {}", hookName, e.getMessage()); } Prevention
- Keep hooks small and defensive
- Null-check config values hooks depend on
- Log and swallow inside the hook for non-critical cleanup
When it happens
Trigger: Any registered lifecycle hook callable (`callable.call(null)`) throws — e.g. a `configure userDefinedHook` / `afterScenario` style hook whose JS or Java lambda raises.
Common situations: Hooks calling karate features that fail; null dereferences on missing config values; environment teardown scripts that error (DB cleanup, API calls).
Related errors
- onStepFailure hook threw, continuing
- append() needs at least two arguments
- appendTo() needs at least two arguments: list and item(s)
- assert expression must return boolean:
- assert failed:
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/655bfd5131a58aae.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java:2252
channels = new ArrayList<>();
}
channels.add(channel);
}
/**
* Invoke a lifecycle hook (beforeScenario / afterScenario) if it is a callable.
* Returns null on success or no-op; returns the Throwable on failure.
* Exceptions are always logged WARN (callers decide whether to surface as a scenario failure).
*/
private Throwable invokeHook(Object hookRef, String hookName) {
if (!(hookRef instanceof JavaCallable callable)) {
return null;
}
try {
callable.call(null);
return null;
} catch (Exception e) {
logger.warn("{} hook failed: {}", hookName, e.getMessage());
return e;
}
}
/**
* Run a lifecycle hook and append a synthetic StepResult describing the invocation
* to the scenario's step list so it renders in the HTML report alongside regular
* Gherkin steps. The synthetic step carries any karate.call() results produced inside
* the hook (via the same buffer real steps use) plus the hook's log / embed output.
* Returns null when there is no callable hook configured or the hook passed; returns
* the Throwable so callers can apply the existing stop/continue semantics.
*/
private Throwable invokeAndRecordHook(Object hookRef, String hookName) {
if (!(hookRef instanceof JavaCallable)) {
return null;
}
long startTime = System.currentTimeMillis();
long startNanos = System.nanoTime();View on GitHub (pinned to a22eb90246)