karatelabs/karate · error · RuntimeException

configure 'logging' expects a map, got

Error message

configure 'logging' expects a map, got: ${value == null ? "null" : value.getClass().getName()}

What it means

The 'configure logging' key must be assigned a Map (e.g. 'configure logging = { report: "info", mask: {...} }'). If the assigned value is null or any non-map type (String, number, boolean), configureLogging throws with the actual type name.

Solutions

  1. Change the value to a map, e.g. 'configure logging = { report: "info" }'
  2. If you meant to set the report level, put it under the 'report' key inside the map
  3. Check karate-config.js for variable interpolation that may produce null or a string

Example fix

// before
* configure logging = 'info'
// after
* configure logging = { report: 'info' }
Defensive patterns

Strategy: type-guard

Validate before calling

var isLoggingMap = function (v) { return v !== null && typeof v === 'object' && !(v instanceof Array); };

Type guard

function isPlainObject(v) { return v != null && v.getClass && java.util.Map.class.isInstance(v); }

Try / catch

try { karate.configure('logging', v); } catch (RuntimeException e) { if (e.getMessage().contains("configure 'logging' expects a map")) { log.error('logging must be an object/map, got: ' + typeof v); } throw e; }

Prevention

When it happens

Trigger: Writing 'configure logging = "info"' (string instead of map), 'configure logging = true', or 'configure logging = null' in a feature file or karate-config.js.

Common situations: Users assuming logging takes a level string directly (the level goes inside the map under 'report'); porting from other frameworks where a simple value is expected; JS code assigning a non-object to logging.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/KarateConfig.java:623

            if (map.containsKey("logLevel")) {
                throw new RuntimeException(
                        "'configure report = { logLevel: ... }' is no longer supported; use "
                                + "'configure logging = { report: \"info\" }' instead "
                                + "(see docs/MIGRATION_GUIDE.md#logging)");
            }
            if (map.containsKey("showLog")) {
                this.report.put("showLog", toBoolean(map.get("showLog")));
            }
            if (map.containsKey("showAllSteps")) {
                this.report.put("showAllSteps", toBoolean(map.get("showAllSteps")));
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void configureLogging(Object value) {
        if (!(value instanceof Map<?, ?> raw)) {
            throw new RuntimeException("configure 'logging' expects a map, got: "
                    + (value == null ? "null" : value.getClass().getName()));
        }
        Map<String, Object> map = (Map<String, Object>) raw;
        if (map.containsKey("report")) {
            String levelStr = toString(map.get("report"));
            this.logging.put("report", levelStr);
            LogContext.setLogLevel(LogLevel.valueOf(levelStr.toUpperCase()));
        }
        if (map.containsKey("console")) {
            String levelStr = toString(map.get("console"));
            this.logging.put("console", levelStr);
            LogContext.setRuntimeLogLevel(levelStr);
        }
        if (map.containsKey("pretty")) {
            boolean pretty = toBoolean(map.get("pretty"));
            this.logging.put("pretty", pretty);
            LogContext.get().setPretty(pretty);
        }

View on GitHub (pinned to a22eb90246)