karatelabs/karate · warning

ErrorRunEvent dispatch failed, continuing

Error message

ErrorRunEvent dispatch failed, continuing: {}

What it means

After a scenario error, Karate fires an `ErrorRunEvent` to suite listeners (for reporting). If dispatching to any listener throws, this warning is logged and execution continues — a broken listener can never break the run.

Solutions

  1. Inspect `t.toString()` to identify which listener threw
  2. Wrap your listener's handler body in its own try/catch
  3. Verify listener resources (files, connections) are still valid at event time
  4. Update or pin the reporting plugin version

Example fix

// before
public void onError(ErrorRunEvent e) { report.append(e.getError().getMessage()); }
// after
public void onError(ErrorRunEvent e) { try { report.append(String.valueOf(e.getError().getMessage())); } catch (Exception ex) { log.warn("listener failed", ex); } }
Defensive patterns

Strategy: try-catch

Try / catch

// In your RunListener:
public void onError(ErrorRunEvent e) { try { handle(e); } catch (Throwable t) { log.warn("listener failed", t); } }

Prevention

When it happens

Trigger: A custom `RunListener`/suite event subscriber throws inside its error-event handler when `suite.fireEvent(ErrorRunEvent.of(...))` iterates listeners.

Common situations: Custom reporting listeners writing to a dead file handle or DB; third-party CI listeners with bugs; listener code referencing null scenario state.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/bbf81c017d45db26. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java:2095

        return info;
    }

    private void fireErrorEvent(StepResult sr) {
        Suite suite = featureRuntime == null ? null : featureRuntime.getSuite();
        if (suite == null) {
            return;
        }
        // @report=false scenarios are designed to keep sensitive content out of
        // every reporting surface (HTML, JSONL). Skipping the bus fire here is
        // the cheapest way to honor that contract — the failure still counts,
        // it just doesn't surface raw error text to listeners.
        if (reportDisabled) {
            return;
        }
        try {
            suite.fireEvent(ErrorRunEvent.of(sr.getError(), this));
        } catch (Throwable t) {
            logger.warn("ErrorRunEvent dispatch failed, continuing: {}", t.toString());
        }
    }

    /**
     * Tracks whether the {@code onStepFailure} hook explicitly chose a
     * soft-assert / hard-stop outcome. Last call wins; if neither is called,
     * {@link #resolve(boolean)} returns the supplied static-config default.
     */
    private static final class FailureDecision {

        private Boolean override;

        void proceed() {
            override = Boolean.TRUE;
        }

        void stop() {
            override = Boolean.FALSE;

View on GitHub (pinned to a22eb90246)