karatelabs/karate · error · IllegalArgumentException

invalid log replay level: '', expected one of: trace…

Error message

invalid log replay level: '', expected one of: trace, debug, info, warn, error

What it means

KarateProtocolBuilder.logReplayLevel(String) maps a string to the LogLevel enum (trace, debug, info, warn, error). Any null, empty, or unrecognized level throws IllegalArgumentException listing the valid values. This controls which log lines are retained/replayed in Gatling reports.

Solutions

  1. Pass one of: "trace", "debug", "info", "warn", "error" (case-insensitive)
  2. Fix the config value feeding logReplayLevel; guard with a default: level.isEmpty() ? "error" : level
  3. If you wanted to disable replay entirely, use logReplay(OFF) instead of changing the level

Example fix

// before
protocol.logReplayLevel(System.getProperty("log.level", ""));
// after
protocol.logReplayLevel(System.getProperty("log.level", "error"));
Defensive patterns

Strategy: validation

Validate before calling

String l = level == null ? "error" : level.trim().toLowerCase();
if (!List.of("trace","debug","info","warn","error").contains(l)) { throw new IllegalArgumentException("log level must be trace|debug|info|warn|error"); }

Try / catch

try {
  protocol.logReplayLevel(level);
} catch (IllegalArgumentException e) {
  protocol.logReplayLevel("error");
}

Prevention

When it happens

Trigger: Calling logReplayLevel("") or logReplayLevel("verbose") / any misspelled level; passing a level sourced from an unset config property; passing a non-LogLevel-compatible name like 'warning' or 'err'.

Common situations: Configuration strings using log4j-style names ('warn' ok, 'warning' not); empty string from a properties file placeholder; renamed constants between library versions.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at karate-gatling/src/main/java/io/karatelabs/gatling/KarateProtocolBuilder.java:132

    }

    /** {@link #logReplay(KarateLogReplay)} by name: {@code "off"}, {@code "failed"}, {@code "all"}. */
    public KarateProtocolBuilder logReplay(String mode) {
        return logReplay(KarateLogReplay.fromString(mode));
    }

    /**
     * The level the replayed output is logged at, defaulting to {@code error} so it survives the
     * quiet Logback config a load run usually has. Accepts {@code trace}, {@code debug},
     * {@code info}, {@code warn}, {@code error}.
     *
     * @return this builder for chaining
     */
    public KarateProtocolBuilder logReplayLevel(String level) {
        try {
            this.logReplayLevel = LogLevel.valueOf(level.trim().toUpperCase(Locale.ROOT));
        } catch (Exception e) {
            throw new IllegalArgumentException("invalid log replay level: '" + level
                    + "', expected one of: trace, debug, info, warn, error");
        }
        return this;
    }

    /**
     * How many already-passed feature logs to retain per virtual user in
     * {@link KarateLogReplay#ALL} mode, defaulting to {@value LogReplayer#DEFAULT_LIMIT}. This text
     * is held in memory for every virtual user until it is replayed or dropped, so raise it with
     * the run's concurrency in mind. Once a replay happens the retained logs are cleared, which is
     * what keeps the window to the current iteration in the common case — Gatling gives an action
     * no iteration boundary to hook, so the guarantee is "the last N Karate calls for this user".
     *
     * @return this builder for chaining
     */
    public KarateProtocolBuilder logReplayLimit(int limit) {
        if (limit < 1) {
            // zero would retain nothing AND report nothing dropped, quietly turning ALL into

View on GitHub (pinned to a22eb90246)