karatelabs/karate · info

retry succeeded after

Error message

retry succeeded after {} attempt(s): eval {}

What it means

This informational warning confirms that a transient-error retry loop for Runtime.evaluate succeeded on a non-first attempt: after 'attempt' failed tries (context not found, context destroyed, etc.), the CDP message finally succeeded. It is logged only when attempt > 0 and the response is not an error, and is purely diagnostic — no failure occurred. Its purpose is to make retry flakiness visible in CI logs.

Solutions

  1. No action needed on success — this is the retry mechanism working as designed.
  2. If it fires frequently for the same expression, add an explicit wait (waitFor/url transitions) before evaluating to reduce churn.
  3. Track frequency; a rising rate suggests environmental slowness or pages that swap contexts aggressively.
Defensive patterns

Strategy: retry

Prevention

When it happens

Trigger: script()/eval where the evalRetry loop caught a transient CDP context error on earlier attempt(s), then message.send() returned a successful response.

Common situations: Evaluations racing navigation-driven context swaps, CI load delaying execution-context registration, tests reading DOM right after frame switches or redirects.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/driver/cdp/CdpDriver.java:1926

                    // Safety net only: the readiness future (getFrameContext awaits it)
                    // normally guarantees a live context here. A context can still die
                    // between the await and the send (e.g. a click triggered a navigation);
                    // the navigation's executionContextsCleared event invalidates the
                    // future, so the retry's getFrameContext() blocks for the replacement
                    // context on its own. We deliberately do NOT invalidate from here: a
                    // -32000 that is NOT a navigation would otherwise strand the future
                    // incomplete (no new executionContextCreated would ever arrive) and
                    // make every later eval wait out the full timeout.
                    logger.warn("transient context error, retry {}/{}: {}", attempt + 1, maxRetries, truncate(expression, 100));
                    sleep(transientInterval);
                    continue;
                }
                logger.warn("retry exhausted for transient context error: {}", truncate(expression, 100));
            }

            // Success or non-transient error
            if (attempt > 0 && !response.isError()) {
                logger.warn("retry succeeded after {} attempt(s): eval {}", attempt, truncate(expression, 50));
            }
            return response;
        }

        // Should not reach here, but return last response if somehow we do
        throw new RuntimeException("eval retry logic error for: " + expression);
    }

    /**
     * Check if a CDP response indicates a transient execution context error
     * that should be retried.
     *
     * DESIGN NOTES:
     * - CDP error code -32000 is a generic "server error" used for ALL execution context issues
     * - Chrome uses this code for: context destroyed, context not found, target navigated, etc.
     * - Rather than matching specific messages (which may vary by Chrome version), we retry
     *   all -32000 errors since they're all related to transient context state
     * - This is more robust than Puppeteer's message-matching approach and handles edge cases

View on GitHub (pinned to a22eb90246)